コード例 #1
0
static int at32_rtc_ioctl(struct device *dev, unsigned int cmd,
			unsigned long arg)
{
	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
	int ret = 0;

	spin_lock_irq(&rtc->lock);

	switch (cmd) {
	case RTC_AIE_ON:
		if (rtc_readl(rtc, VAL) > rtc->alarm_time) {
			ret = -EINVAL;
			break;
		}
		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
				| RTC_BIT(CTRL_TOPEN));
		rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
		rtc_writel(rtc, IER, RTC_BIT(IER_TOPI));
		break;
	case RTC_AIE_OFF:
		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
				& ~RTC_BIT(CTRL_TOPEN));
		rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
		rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
		break;
	default:
		ret = -ENOIOCTLCMD;
		break;
	}

	spin_unlock_irq(&rtc->lock);

	return ret;
}
コード例 #2
0
ファイル: rtc-at32ap700x.c プロジェクト: AshishNamdev/linux
static int at32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
	int ret = 0;

	spin_lock_irq(&rtc->lock);

	if (enabled) {
		if (rtc_readl(rtc, VAL) > rtc->alarm_time) {
			ret = -EINVAL;
			goto out;
		}
		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
				| RTC_BIT(CTRL_TOPEN));
		rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
		rtc_writel(rtc, IER, RTC_BIT(IER_TOPI));
	} else {
		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
				& ~RTC_BIT(CTRL_TOPEN));
		rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
		rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
	}
out:
	spin_unlock_irq(&rtc->lock);

	return ret;
}
コード例 #3
0
ファイル: rtc-at32ap700x.c プロジェクト: AshishNamdev/linux
static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
	unsigned long rtc_unix_time;
	unsigned long alarm_unix_time;
	int ret;

	rtc_unix_time = rtc_readl(rtc, VAL);

	ret = rtc_tm_to_time(&alrm->time, &alarm_unix_time);
	if (ret)
		return ret;

	if (alarm_unix_time < rtc_unix_time)
		return -EINVAL;

	spin_lock_irq(&rtc->lock);
	rtc->alarm_time = alarm_unix_time;
	rtc_writel(rtc, TOP, rtc->alarm_time);
	if (alrm->enabled)
		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
				| RTC_BIT(CTRL_TOPEN));
	else
		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
				& ~RTC_BIT(CTRL_TOPEN));
	spin_unlock_irq(&rtc->lock);

	return ret;
}
コード例 #4
0
ファイル: rtc-at32ap700x.c プロジェクト: AshishNamdev/linux
static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);

	spin_lock_irq(&rtc->lock);
	rtc_time_to_tm(rtc->alarm_time, &alrm->time);
	alrm->enabled = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0;
	alrm->pending = rtc_readl(rtc, ISR) & RTC_BIT(ISR_TOPI) ? 1 : 0;
	spin_unlock_irq(&rtc->lock);

	return 0;
}
コード例 #5
0
ファイル: rtc-lpc32xx.c プロジェクト: 119-org/hi3518-osdrv
static int lpc32xx_rtc_read_alarm(struct device *dev,
	struct rtc_wkalrm *wkalrm)
{
	struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);

	rtc_time_to_tm(rtc_readl(rtc, LPC32XX_RTC_MATCH0), &wkalrm->time);
	wkalrm->enabled = rtc->alarm_enabled;
	wkalrm->pending = !!(rtc_readl(rtc, LPC32XX_RTC_INTSTAT) &
		LPC32XX_RTC_INTSTAT_MATCH0);

	return rtc_valid_tm(&wkalrm->time);
}
コード例 #6
0
ファイル: rtc-lpc32xx.c プロジェクト: 119-org/hi3518-osdrv
static irqreturn_t lpc32xx_rtc_alarm_interrupt(int irq, void *dev)
{
	struct lpc32xx_rtc *rtc = dev;

	spin_lock(&rtc->lock);

	/* Disable alarm interrupt */
	rtc_writel(rtc, LPC32XX_RTC_CTRL,
		rtc_readl(rtc, LPC32XX_RTC_CTRL) &
			  ~LPC32XX_RTC_CTRL_MATCH0);
	rtc->alarm_enabled = 0;

	/*
	 * Write a large value to the match value so the RTC won't
	 * keep firing the match status
	 */
	rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF);
	rtc_writel(rtc, LPC32XX_RTC_INTSTAT, LPC32XX_RTC_INTSTAT_MATCH0);

	spin_unlock(&rtc->lock);

	rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);

	return IRQ_HANDLED;
}
コード例 #7
0
ファイル: rtc-lpc32xx.c プロジェクト: 119-org/hi3518-osdrv
static int lpc32xx_rtc_set_alarm(struct device *dev,
	struct rtc_wkalrm *wkalrm)
{
	struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
	unsigned long alarmsecs;
	u32 tmp;
	int ret;

	ret = rtc_tm_to_time(&wkalrm->time, &alarmsecs);
	if (ret < 0) {
		dev_warn(dev, "Failed to convert time: %d\n", ret);
		return ret;
	}

	spin_lock_irq(&rtc->lock);

	/* Disable alarm during update */
	tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL);
	rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp & ~LPC32XX_RTC_CTRL_MATCH0);

	rtc_writel(rtc, LPC32XX_RTC_MATCH0, alarmsecs);

	rtc->alarm_enabled = wkalrm->enabled;
	if (wkalrm->enabled) {
		rtc_writel(rtc, LPC32XX_RTC_INTSTAT,
			   LPC32XX_RTC_INTSTAT_MATCH0);
		rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp |
			   LPC32XX_RTC_CTRL_MATCH0);
	}

	spin_unlock_irq(&rtc->lock);

	return 0;
}
コード例 #8
0
static void tegra_clocksource_resume(struct clocksource *cs)
{
    u32 usec;

    usec = timer_readl(TIMERUS_CNTR_1US);
    tegra_usec_start_time =
        rtc_readl(RTC_MILLISECONDS_REG)*1000 +
        (cycle_t)rtc_readl(RTC_SHADOW_SECONDS)*1000000;
    /*  On first time power up the usec timer will be greater than the rtc,
        since it has smaller time steps.  A negative tegra_usec_start_time is
        not desirable in this case. */
    if ((cycle_t)usec > tegra_usec_start_time)
        tegra_usec_start_time = 0;
    else
        tegra_usec_start_time -= usec;
}
コード例 #9
0
ファイル: rtc-omap.c プロジェクト: forgivemyheart/linux
static int rtc_pinconf_get(struct pinctrl_dev *pctldev,
			unsigned int pin, unsigned long *config)
{
	struct omap_rtc *rtc = pinctrl_dev_get_drvdata(pctldev);
	unsigned int param = pinconf_to_config_param(*config);
	u32 val;
	u16 arg = 0;

	rtc->type->unlock(rtc);
	val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
	rtc->type->lock(rtc);

	switch (param) {
	case PIN_CONFIG_INPUT_ENABLE:
		if (!(val & OMAP_RTC_PMIC_EXT_WKUP_EN(pin)))
			return -EINVAL;
		break;
	case PIN_CONFIG_ACTIVE_HIGH:
		if (val & OMAP_RTC_PMIC_EXT_WKUP_POL(pin))
			return -EINVAL;
		break;
	default:
		return -ENOTSUPP;
	};

	*config = pinconf_to_config_packed(param, arg);

	return 0;
}
コード例 #10
0
ファイル: rtc-at32ap700x.c プロジェクト: AshishNamdev/linux
static int at32_rtc_readtime(struct device *dev, struct rtc_time *tm)
{
	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
	unsigned long now;

	now = rtc_readl(rtc, VAL);
	rtc_time_to_tm(now, tm);

	return 0;
}
コード例 #11
0
ファイル: rtc-lpc32xx.c プロジェクト: 119-org/hi3518-osdrv
static int lpc32xx_rtc_read_time(struct device *dev, struct rtc_time *time)
{
	unsigned long elapsed_sec;
	struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);

	elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT);
	rtc_time_to_tm(elapsed_sec, time);

	return rtc_valid_tm(time);
}
コード例 #12
0
ファイル: rtc-omap.c プロジェクト: krzk/linux
static int omap_rtc_scratch_read(void *priv, unsigned int offset, void *_val,
				 size_t bytes)
{
	struct omap_rtc	*rtc = priv;
	u32 *val = _val;
	int i;

	for (i = 0; i < bytes / 4; i++)
		val[i] = rtc_readl(rtc,
				   OMAP_RTC_SCRATCH0_REG + offset + (i * 4));

	return 0;
}
コード例 #13
0
ファイル: rtc-omap.c プロジェクト: forgivemyheart/linux
/*
 * omap_rtc_poweroff: RTC-controlled power off
 *
 * The RTC can be used to control an external PMIC via the pmic_power_en pin,
 * which can be configured to transition to OFF on ALARM2 events.
 *
 * Notes:
 * The two-second alarm offset is the shortest offset possible as the alarm
 * registers must be set before the next timer update and the offset
 * calculation is too heavy for everything to be done within a single access
 * period (~15 us).
 *
 * Called with local interrupts disabled.
 */
static void omap_rtc_power_off(void)
{
	struct omap_rtc *rtc = omap_rtc_power_off_rtc;
	struct rtc_time tm;
	unsigned long now;
	u32 val;

	rtc->type->unlock(rtc);
	/* enable pmic_power_en control */
	val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
	rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN);

	/* set alarm two seconds from now */
	omap_rtc_read_time_raw(rtc, &tm);
	bcd2tm(&tm);
	rtc_tm_to_time(&tm, &now);
	rtc_time_to_tm(now + 2, &tm);

	if (tm2bcd(&tm) < 0) {
		dev_err(&rtc->rtc->dev, "power off failed\n");
		return;
	}

	rtc_wait_not_busy(rtc);

	rtc_write(rtc, OMAP_RTC_ALARM2_SECONDS_REG, tm.tm_sec);
	rtc_write(rtc, OMAP_RTC_ALARM2_MINUTES_REG, tm.tm_min);
	rtc_write(rtc, OMAP_RTC_ALARM2_HOURS_REG, tm.tm_hour);
	rtc_write(rtc, OMAP_RTC_ALARM2_DAYS_REG, tm.tm_mday);
	rtc_write(rtc, OMAP_RTC_ALARM2_MONTHS_REG, tm.tm_mon);
	rtc_write(rtc, OMAP_RTC_ALARM2_YEARS_REG, tm.tm_year);

	/*
	 * enable ALARM2 interrupt
	 *
	 * NOTE: this fails on AM3352 if rtc_write (writeb) is used
	 */
	val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
	rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG,
			val | OMAP_RTC_INTERRUPTS_IT_ALARM2);
	rtc->type->lock(rtc);

	/*
	 * Wait for alarm to trigger (within two seconds) and external PMIC to
	 * power off the system. Add a 500 ms margin for external latencies
	 * (e.g. debounce circuits).
	 */
	mdelay(2500);
}
コード例 #14
0
ファイル: rtc-at32ap700x.c プロジェクト: AshishNamdev/linux
static irqreturn_t at32_rtc_interrupt(int irq, void *dev_id)
{
	struct rtc_at32ap700x *rtc = (struct rtc_at32ap700x *)dev_id;
	unsigned long isr = rtc_readl(rtc, ISR);
	unsigned long events = 0;
	int ret = IRQ_NONE;

	spin_lock(&rtc->lock);

	if (isr & RTC_BIT(ISR_TOPI)) {
		rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
		rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
				& ~RTC_BIT(CTRL_TOPEN));
		rtc_writel(rtc, VAL, rtc->alarm_time);
		events = RTC_AF | RTC_IRQF;
		rtc_update_irq(rtc->rtc, 1, events);
		ret = IRQ_HANDLED;
	}

	spin_unlock(&rtc->lock);

	return ret;
}
コード例 #15
0
ファイル: rtc-lpc32xx.c プロジェクト: 119-org/hi3518-osdrv
/* Unconditionally disable the alarm */
static int lpc32xx_rtc_freeze(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev);

	spin_lock_irq(&rtc->lock);

	rtc_writel(rtc, LPC32XX_RTC_CTRL,
		rtc_readl(rtc, LPC32XX_RTC_CTRL) &
			  ~LPC32XX_RTC_CTRL_MATCH0);

	spin_unlock_irq(&rtc->lock);

	return 0;
}
コード例 #16
0
ファイル: rtc-lpc32xx.c プロジェクト: 119-org/hi3518-osdrv
static int lpc32xx_rtc_thaw(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev);

	if (rtc->alarm_enabled) {
		spin_lock_irq(&rtc->lock);

		rtc_writel(rtc, LPC32XX_RTC_CTRL,
			   rtc_readl(rtc, LPC32XX_RTC_CTRL) |
			   LPC32XX_RTC_CTRL_MATCH0);

		spin_unlock_irq(&rtc->lock);
	}

	return 0;
}
コード例 #17
0
ファイル: rtc-lpc32xx.c プロジェクト: 119-org/hi3518-osdrv
static int lpc32xx_rtc_set_mmss(struct device *dev, unsigned long secs)
{
	struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
	u32 tmp;

	spin_lock_irq(&rtc->lock);

	/* RTC must be disabled during count update */
	tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL);
	rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | LPC32XX_RTC_CTRL_CNTR_DIS);
	rtc_writel(rtc, LPC32XX_RTC_UCOUNT, secs);
	rtc_writel(rtc, LPC32XX_RTC_DCOUNT, 0xFFFFFFFF - secs);
	rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp &= ~LPC32XX_RTC_CTRL_CNTR_DIS);

	spin_unlock_irq(&rtc->lock);

	return 0;
}
コード例 #18
0
ファイル: rtc-omap.c プロジェクト: forgivemyheart/linux
static int rtc_pinconf_set(struct pinctrl_dev *pctldev,
			unsigned int pin, unsigned long *configs,
			unsigned int num_configs)
{
	struct omap_rtc *rtc = pinctrl_dev_get_drvdata(pctldev);
	u32 val;
	unsigned int param;
	u16 param_val;
	int i;

	rtc->type->unlock(rtc);
	val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
	rtc->type->lock(rtc);

	/* active low by default */
	val |= OMAP_RTC_PMIC_EXT_WKUP_POL(pin);

	for (i = 0; i < num_configs; i++) {
		param = pinconf_to_config_param(configs[i]);
		param_val = pinconf_to_config_argument(configs[i]);

		switch (param) {
		case PIN_CONFIG_INPUT_ENABLE:
			if (param_val)
				val |= OMAP_RTC_PMIC_EXT_WKUP_EN(pin);
			else
				val &= ~OMAP_RTC_PMIC_EXT_WKUP_EN(pin);
			break;
		case PIN_CONFIG_ACTIVE_HIGH:
			val &= ~OMAP_RTC_PMIC_EXT_WKUP_POL(pin);
			break;
		default:
			dev_err(&rtc->rtc->dev, "Property %u not supported\n",
				param);
			return -ENOTSUPP;
		}
	}

	rtc->type->unlock(rtc);
	rtc_writel(rtc, OMAP_RTC_PMIC_REG, val);
	rtc->type->lock(rtc);

	return 0;
}
コード例 #19
0
ファイル: rtc-lpc32xx.c プロジェクト: 119-org/hi3518-osdrv
static int lpc32xx_rtc_alarm_irq_enable(struct device *dev,
	unsigned int enabled)
{
	struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
	u32 tmp;

	spin_lock_irq(&rtc->lock);
	tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL);

	if (enabled) {
		rtc->alarm_enabled = 1;
		tmp |= LPC32XX_RTC_CTRL_MATCH0;
	} else {
		rtc->alarm_enabled = 0;
		tmp &= ~LPC32XX_RTC_CTRL_MATCH0;
	}

	rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp);
	spin_unlock_irq(&rtc->lock);

	return 0;
}
コード例 #20
0
ファイル: rtc-at32ap700x.c プロジェクト: AshishNamdev/linux
static int __init at32_rtc_probe(struct platform_device *pdev)
{
	struct resource	*regs;
	struct rtc_at32ap700x *rtc;
	int irq;
	int ret;

	rtc = devm_kzalloc(&pdev->dev, sizeof(struct rtc_at32ap700x),
			   GFP_KERNEL);
	if (!rtc)
		return -ENOMEM;

	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!regs) {
		dev_dbg(&pdev->dev, "no mmio resource defined\n");
		return -ENXIO;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq <= 0) {
		dev_dbg(&pdev->dev, "could not get irq\n");
		return -ENXIO;
	}

	rtc->irq = irq;
	rtc->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
	if (!rtc->regs) {
		dev_dbg(&pdev->dev, "could not map I/O memory\n");
		return -ENOMEM;
	}
	spin_lock_init(&rtc->lock);

	/*
	 * Maybe init RTC: count from zero at 1 Hz, disable wrap irq.
	 *
	 * Do not reset VAL register, as it can hold an old time
	 * from last JTAG reset.
	 */
	if (!(rtc_readl(rtc, CTRL) & RTC_BIT(CTRL_EN))) {
		rtc_writel(rtc, CTRL, RTC_BIT(CTRL_PCLR));
		rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
		rtc_writel(rtc, CTRL, RTC_BF(CTRL_PSEL, 0xe)
				| RTC_BIT(CTRL_EN));
	}

	ret = devm_request_irq(&pdev->dev, irq, at32_rtc_interrupt, IRQF_SHARED,
				"rtc", rtc);
	if (ret) {
		dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
		return ret;
	}

	platform_set_drvdata(pdev, rtc);

	rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
				&at32_rtc_ops, THIS_MODULE);
	if (IS_ERR(rtc->rtc)) {
		dev_dbg(&pdev->dev, "could not register rtc device\n");
		return PTR_ERR(rtc->rtc);
	}

	device_init_wakeup(&pdev->dev, 1);

	dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n",
			(unsigned long)rtc->regs, rtc->irq);

	return 0;
}
コード例 #21
0
ファイル: rtc-lpc32xx.c プロジェクト: 119-org/hi3518-osdrv
static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev)
{
	struct resource *res;
	struct lpc32xx_rtc *rtc;
	resource_size_t size;
	int rtcirq;
	u32 tmp;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "Can't get memory resource\n");
		return -ENOENT;
	}

	rtcirq = platform_get_irq(pdev, 0);
	if (rtcirq < 0 || rtcirq >= NR_IRQS) {
		dev_warn(&pdev->dev, "Can't get interrupt resource\n");
		rtcirq = -1;
	}

	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
	if (unlikely(!rtc)) {
		dev_err(&pdev->dev, "Can't allocate memory\n");
		return -ENOMEM;
	}
	rtc->irq = rtcirq;

	size = resource_size(res);

	if (!devm_request_mem_region(&pdev->dev, res->start, size,
				     pdev->name)) {
		dev_err(&pdev->dev, "RTC registers are not free\n");
		return -EBUSY;
	}

	rtc->rtc_base = devm_ioremap(&pdev->dev, res->start, size);
	if (!rtc->rtc_base) {
		dev_err(&pdev->dev, "Can't map memory\n");
		return -ENOMEM;
	}

	spin_lock_init(&rtc->lock);

	/*
	 * The RTC is on a separate power domain and can keep it's state
	 * across a chip power cycle. If the RTC has never been previously
	 * setup, then set it up now for the first time.
	 */
	tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL);
	if (rtc_readl(rtc, LPC32XX_RTC_KEY) != LPC32XX_RTC_KEY_ONSW_LOADVAL) {
		tmp &= ~(LPC32XX_RTC_CTRL_SW_RESET |
			LPC32XX_RTC_CTRL_CNTR_DIS |
			LPC32XX_RTC_CTRL_MATCH0 |
			LPC32XX_RTC_CTRL_MATCH1 |
			LPC32XX_RTC_CTRL_ONSW_MATCH0 |
			LPC32XX_RTC_CTRL_ONSW_MATCH1 |
			LPC32XX_RTC_CTRL_ONSW_FORCE_HI);
		rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp);

		/* Clear latched interrupt states */
		rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF);
		rtc_writel(rtc, LPC32XX_RTC_INTSTAT,
			   LPC32XX_RTC_INTSTAT_MATCH0 |
			   LPC32XX_RTC_INTSTAT_MATCH1 |
			   LPC32XX_RTC_INTSTAT_ONSW);

		/* Write key value to RTC so it won't reload on reset */
		rtc_writel(rtc, LPC32XX_RTC_KEY,
			   LPC32XX_RTC_KEY_ONSW_LOADVAL);
	} else {
		rtc_writel(rtc, LPC32XX_RTC_CTRL,
			   tmp & ~LPC32XX_RTC_CTRL_MATCH0);
	}

	platform_set_drvdata(pdev, rtc);

	rtc->rtc = rtc_device_register(RTC_NAME, &pdev->dev, &lpc32xx_rtc_ops,
		THIS_MODULE);
	if (IS_ERR(rtc->rtc)) {
		dev_err(&pdev->dev, "Can't get RTC\n");
		platform_set_drvdata(pdev, NULL);
		return PTR_ERR(rtc->rtc);
	}

	/*
	 * IRQ is enabled after device registration in case alarm IRQ
	 * is pending upon suspend exit.
	 */
	if (rtc->irq >= 0) {
		if (devm_request_irq(&pdev->dev, rtc->irq,
				     lpc32xx_rtc_alarm_interrupt,
				     IRQF_DISABLED, pdev->name, rtc) < 0) {
			dev_warn(&pdev->dev, "Can't request interrupt.\n");
			rtc->irq = -1;
		} else {
			device_init_wakeup(&pdev->dev, 1);
		}
	}

	return 0;
}
コード例 #22
0
void read_persistent_clock(struct timespec *ts)
{
    ts->tv_nsec = rtc_readl(RTC_MILLISECONDS_REG) * 1000000;
    ts->tv_sec = rtc_readl(RTC_SHADOW_SECONDS);
}