Exemplo n.º 1
0
/*!
 * This function sets the RTC alarm based on passed in alrm.
 *
 * @param  alrm         the alarm value to be set in the RTC
 *
 * @return  0 if successful; non-zero otherwise.
 */
static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
	void __iomem *ioaddr = pdata->ioaddr;
	int ret;

	spin_lock_irq(&rtc_lock);
	if (rtc_valid_tm(&alrm->time)) {
		if (alrm->time.tm_sec > 59 ||
		    alrm->time.tm_hour > 23 || alrm->time.tm_min > 59) {
			ret = -EINVAL;
			goto out;
		}
		ret = rtc_update_alarm(dev, &alrm->time);
	} else {
		if ((ret = rtc_valid_tm(&alrm->time)))
			goto out;
		ret = rtc_update_alarm(dev, &alrm->time);
	}

	if (ret == 0) {
		memcpy(&g_rtc_alarm, &alrm->time, sizeof(struct rtc_time));

		if (alrm->enabled) {
			writew((readw(ioaddr + RTC_RTCIENR) | RTC_ALM_BIT),
			       ioaddr + RTC_RTCIENR);
		} else {
			writew((readw(ioaddr + RTC_RTCIENR) & ~RTC_ALM_BIT),
			       ioaddr + RTC_RTCIENR);
		}
	}
      out:
	spin_unlock_irq(&rtc_lock);

	return ret;
}
Exemplo n.º 2
0
/*!
 * This function sets the RTC alarm based on passed in alrm.
 *
 * @param  alrm         the alarm value to be set in the RTC
 *
 * @return  0 if successful; non-zero otherwise.
 */
static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct rtc_drv_data *pdata = dev_get_drvdata(dev);
	void __iomem *ioaddr = pdata->ioaddr;
	unsigned long lock_flags = 0;
	u32 lp_cr;
	int ret;

	if (rtc_valid_tm(&alrm->time)) {
		if (alrm->time.tm_sec > 59 ||
		    alrm->time.tm_hour > 23 || alrm->time.tm_min > 59) {
			return -EINVAL;
		}
	}

	spin_lock_irqsave(&rtc_lock, lock_flags);
	lp_cr = __raw_readl(ioaddr + SRTC_LPCR);

	ret = rtc_update_alarm(dev, &alrm->time);
	if (ret)
		goto out;

	if (alrm->enabled)
		lp_cr |= (SRTC_LPCR_ALP | SRTC_LPCR_WAE);
	else
		lp_cr &= ~(SRTC_LPCR_ALP | SRTC_LPCR_WAE);

	if (lp_cr & SRTC_LPCR_ALL_INT_EN) {
		if (!pdata->irq_enable) {
			enable_irq(pdata->irq);
			pdata->irq_enable = true;
		}
	} else {
		if (pdata->irq_enable) {
			disable_irq(pdata->irq);
			pdata->irq_enable = false;
		}
	}

	__raw_writel(lp_cr, ioaddr + SRTC_LPCR);

out:
	spin_unlock_irqrestore(&rtc_lock, lock_flags);
	rtc_write_sync_lp(ioaddr);
	return ret;
}
Exemplo n.º 3
0
/*!
 * This function is the RTC interrupt service routine.
 *
 * @param  irq          RTC IRQ number
 * @param  dev_id       device ID which is not used
 *
 * @return IRQ_HANDLED as defined in the include/linux/interrupt.h file.
 */
static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
{
	struct platform_device *pdev = dev_id;
	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
	void __iomem *ioaddr = pdata->ioaddr;
	u32 status;
	u32 events = 0;
	spin_lock(&rtc_lock);
	status = readw(ioaddr + RTC_RTCISR) & readw(ioaddr + RTC_RTCIENR);
	/* clear interrupt sources */
	writew(status, ioaddr + RTC_RTCISR);

	/* clear alarm interrupt if it has occurred */
	if (status & RTC_ALM_BIT) {
		status &= ~RTC_ALM_BIT;
	}

	/* update irq data & counter */
	if (status & RTC_ALM_BIT) {
		events |= (RTC_AF | RTC_IRQF);
	}
	if (status & RTC_1HZ_BIT) {
		events |= (RTC_UF | RTC_IRQF);
	}
	if (status & PIT_ALL_ON) {
		events |= (RTC_PF | RTC_IRQF);
	}

	if ((status & RTC_ALM_BIT) && rtc_valid_tm(&g_rtc_alarm)) {
		rtc_update_alarm(&pdev->dev, &g_rtc_alarm);
	}

	spin_unlock(&rtc_lock);
	rtc_update_irq(pdata->rtc, 1, events);
	return IRQ_HANDLED;
}