Beispiel #1
0
/* 
 * Read timer or alarm interrupts register.
 */
static int get_rtc_irq_bit(unsigned char *val)
{
	int ret;

	ret = twl4030_rtc_read_u8(val, REG_RTC_INTERRUPTS_REG);
	return ret;
}
/*
 * Gets current TWL4030 RTC time and date parameters.
 *
 * The RTC's time/alarm representation is not what gmtime(3) requires
 * Linux to use:
 *
 *  - Months are 1..12 vs Linux 0-11
 *  - Years are 0..99 vs Linux 1900..N (we assume 21st century)
 */
static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	unsigned char rtc_data[ALL_TIME_REGS + 1];
	int ret;
	u8 save_control;

	ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
	if (ret < 0)
		return ret;

	save_control |= BIT_RTC_CTRL_REG_GET_TIME_M;

	ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
	if (ret < 0)
		return ret;

	ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data,
			       REG_SECONDS_REG, ALL_TIME_REGS);

	if (ret < 0) {
		dev_err(dev, "rtc_read_time error %d\n", ret);
		return ret;
	}

	tm->tm_sec = bcd2bin(rtc_data[0]);
	tm->tm_min = bcd2bin(rtc_data[1]);
	tm->tm_hour = bcd2bin(rtc_data[2]);
	tm->tm_mday = bcd2bin(rtc_data[3]);
	tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
	tm->tm_year = bcd2bin(rtc_data[5]) + 100;

	return ret;
}
static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc)
{
	unsigned long events = 0;
	int ret = IRQ_NONE;
	int res;
	u8 rd_reg;

#ifdef CONFIG_LOCKDEP
	/* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
	 * we don't want and can't tolerate.  Although it might be
	 * friendlier not to borrow this thread context...
	 */
	local_irq_enable();
#endif

	res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
	if (res)
		goto out;
	/*
	 * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG.
	 * only one (ALARM or RTC) interrupt source may be enabled
	 * at time, we also could check our results
	 * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM]
	 */
	if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
		events |= RTC_IRQF | RTC_AF;
	else
		events |= RTC_IRQF | RTC_UF;

	res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M,
				   REG_RTC_STATUS_REG);
	if (res)
		goto out;

	/* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1
	 * needs 2 reads to clear the interrupt. One read is done in
	 * do_twl4030_pwrirq(). Doing the second read, to clear
	 * the bit.
	 *
	 * FIXME the reason PWR_ISR1 needs an extra read is that
	 * RTC_IF retriggered until we cleared REG_ALARM_M above.
	 * But re-reading like this is a bad hack; by doing so we
	 * risk wrongly clearing status for some other IRQ (losing
	 * the interrupt).  Be smarter about handling RTC_UF ...
	 */
	res = twl4030_i2c_read_u8(TWL4030_MODULE_INT,
			&rd_reg, TWL4030_INT_PWR_ISR1);
	if (res)
		goto out;

	/* Notify RTC core on event */
	rtc_update_irq(rtc, 1, events);

	ret = IRQ_HANDLED;
out:
	return ret;
}
Beispiel #4
0
/* 
 * Enables timer or alarm interrupts.
 */
static int set_rtc_irq_bit(unsigned char bit)
{
	unsigned char val;
	int ret;

	ret = twl4030_rtc_read_u8(&val, REG_RTC_INTERRUPTS_REG);
	if (ret < 0)
		goto set_irq_out;

	val |= bit;
	ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);

set_irq_out:
	return ret;
}
Beispiel #5
0
/* 
 * Gets current TWL4030 RTC time and date parameters.
 */
static int get_rtc_time(struct rtc_time *rtc_tm)
{
	unsigned char rtc_data[ALL_TIME_REGS + 1];
	int ret;
	u8 save_control;

	ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
	if (ret < 0)
    		return ret;

	save_control |= BIT_RTC_CTRL_REG_GET_TIME_M;

	ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
	if (ret < 0)
		return ret;

	ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data,
			       REG_SECONDS_REG, ALL_TIME_REGS);

	if (ret < 0) {
		printk(KERN_ERR "twl4030_rtc: twl4030_i2c_read error.\n");
		return ret;
	}

	rtc_tm->tm_sec = BCD2BIN(rtc_data[0]);
	rtc_tm->tm_min = BCD2BIN(rtc_data[1]);
	rtc_tm->tm_hour = BCD2BIN(rtc_data[2]);
	rtc_tm->tm_mday = BCD2BIN(rtc_data[3]);
	rtc_tm->tm_mon = BCD2BIN(rtc_data[4]);
	rtc_tm->tm_year = BCD2BIN(rtc_data[5]);

	/*
	 * Account for differences between how the RTC uses the values
	 * and how they are defined in a struct rtc_time;
	 */
	if ((rtc_tm->tm_year += (epoch - 1900)) <= 69)
		rtc_tm->tm_year += 100;

	rtc_tm->tm_mon--;

	return ret;
}
Beispiel #6
0
static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	unsigned char save_control;
	unsigned char rtc_data[ALL_TIME_REGS + 1];
	int ret;

	/* Month range is 01..12 */
	tm->tm_mon++;

	rtc_data[1] = BIN2BCD(tm->tm_sec);
	rtc_data[2] = BIN2BCD(tm->tm_min);
	rtc_data[3] = BIN2BCD(tm->tm_hour);
	rtc_data[4] = BIN2BCD(tm->tm_mday);
	rtc_data[5] = BIN2BCD(tm->tm_mon);
	rtc_data[6] = BIN2BCD(tm->tm_year);

	/* Stop RTC while updating the TC registers */
	ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
	if (ret < 0)
		goto out;

	save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
	twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
	if (ret < 0)
		goto out;

	/* update all the alarm registers in one shot */
	ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data,
			        REG_SECONDS_REG, ALL_TIME_REGS);
	if (ret < 0) {
		printk(KERN_ERR "twl4030: twl4030_i2c_write error.\n");
		goto out;
	}

	/* Start back RTC */
	save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
	ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);

out:
	return ret;
}
static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	unsigned char save_control;
	unsigned char rtc_data[ALL_TIME_REGS + 1];
	int ret;

	rtc_data[1] = bin2bcd(tm->tm_sec);
	rtc_data[2] = bin2bcd(tm->tm_min);
	rtc_data[3] = bin2bcd(tm->tm_hour);
	rtc_data[4] = bin2bcd(tm->tm_mday);
	rtc_data[5] = bin2bcd(tm->tm_mon + 1);
	rtc_data[6] = bin2bcd(tm->tm_year - 100);

	/* Stop RTC while updating the TC registers */
	ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
	if (ret < 0)
		goto out;

	save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
	twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
	if (ret < 0)
		goto out;

	/* update all the time registers in one shot */
	ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data,
			REG_SECONDS_REG, ALL_TIME_REGS);
	if (ret < 0) {
		dev_err(dev, "rtc_set_time error %d\n", ret);
		goto out;
	}

	/* Start back RTC */
	save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
	ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);

out:
	return ret;
}
static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
{
	struct rtc_device *rtc;
	int ret = 0;
	int irq = platform_get_irq(pdev, 0);
	u8 rd_reg;

	if (irq < 0)
		return irq;

	rtc = rtc_device_register(pdev->name,
				  &pdev->dev, &twl4030_rtc_ops, THIS_MODULE);
	if (IS_ERR(rtc)) {
		ret = -EINVAL;
		dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
			PTR_ERR(rtc));
		goto out0;

	}

	platform_set_drvdata(pdev, rtc);

	ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);

	if (ret < 0)
		goto out1;

	if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M)
		dev_warn(&pdev->dev, "Power up reset detected.\n");

	if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
		dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n");

	/* Clear RTC Power up reset and pending alarm interrupts */
	ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG);
	if (ret < 0)
		goto out1;

	ret = request_irq(irq, twl4030_rtc_interrupt,
				IRQF_TRIGGER_RISING,
				rtc->dev.bus_id, rtc);
	if (ret < 0) {
		dev_err(&pdev->dev, "IRQ is not free.\n");
		goto out1;
	}

	/* Check RTC module status, Enable if it is off */
	ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG);
	if (ret < 0)
		goto out2;

	if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) {
		dev_info(&pdev->dev, "Enabling TWL4030-RTC.\n");
		rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M;
		ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG);
		if (ret < 0)
			goto out2;
	}

	/* init cached IRQ enable bits */
	ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
	if (ret < 0)
		goto out2;

	return ret;


out2:
	free_irq(irq, rtc);
out1:
	rtc_device_unregister(rtc);
out0:
	return ret;
}
Beispiel #9
0
static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
{
	struct twl4030rtc_platform_data *pdata = pdev->dev.platform_data;
	struct rtc_device *rtc;
	int ret = 0;
	u8 rd_reg;
	
	if (pdata != NULL && pdata->init != NULL) {
		ret = pdata->init();
		if (ret < 0)
			goto out;
	}

	rtc = rtc_device_register(pdev->name,
				  &pdev->dev, &twl4030_rtc_ops, THIS_MODULE);
	if (IS_ERR(rtc)) {
		ret = -EINVAL;
		dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
			PTR_ERR(rtc));
		goto out0;

	}

	platform_set_drvdata(pdev, rtc);

	ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);

	if (ret < 0)
		goto out1;

	if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M)
		dev_warn(&pdev->dev, "Power up reset detected.\n");

	if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
		dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n");

	/* Clear RTC Power up reset and pending alarm interrupts */
	ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG);
	if (ret < 0)
		goto out1;

	ret = request_irq(TWL4030_MODIRQ_PWR, twl4030_rtc_interrupt,
			  IRQF_DISABLED | IRQF_SHARED, rtc->dev.bus_id, rtc);
	if (ret < 0) {
		dev_err(&pdev->dev, "IRQ is not free.\n");
		goto out1;
	} 

	/* Check RTC module status, Enable if it is off */
	ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG);
	if (ret < 0)
		goto out2;

	if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) {
		dev_info(&pdev->dev, "Enabling TWL4030-RTC.\n");
		rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M;
		ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG);
		if (ret < 0)
			goto out2;
	}

	ret = twl4030_i2c_read_u8(TWL4030_MODULE_INT, &rd_reg, REG_PWR_IMR1);
	if (ret < 0)
		goto out2;

	rd_reg &= PWR_RTC_IT_UNMASK;
	/* MASK PWR - we will need this */
	ret = twl4030_i2c_write_u8(TWL4030_MODULE_INT, rd_reg, REG_PWR_IMR1);
	if (ret < 0)
		goto out2;

	ret = twl4030_i2c_read_u8(TWL4030_MODULE_INT, &rd_reg, REG_PWR_EDR1);
	if (ret < 0)
		goto out2;

	/* Rising edge detection enabled, needed for RTC alarm */
	rd_reg |= 0x80;		
	ret = twl4030_i2c_write_u8(TWL4030_MODULE_INT, rd_reg, REG_PWR_EDR1);
	if (ret < 0)
		goto out2;

	return ret;


out2:
	free_irq(TWL4030_MODIRQ_PWR, rtc);
out1:
	rtc_device_unregister(rtc);
out0:
	if (pdata != NULL && pdata->exit != NULL)
		pdata->exit();
out:
	return ret;
}
Beispiel #10
0
static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc)
{
	unsigned long events = 0;
	int ret = IRQ_NONE;
	int res;
	u8 rd_reg;
	
	/* clear the RTC interrupt in TWL4030 power module */
	res = twl4030_i2c_read_u8(TWL4030_MODULE_INT, &rd_reg, REG_PWR_ISR1);
	if (res)
		goto out;

	/* Check if interrupt is sourced by RTC */
	if (!(rd_reg & PWR_RTC_INT_CLR))
		goto out;

	rd_reg |= PWR_RTC_INT_CLR;
	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, rd_reg, REG_PWR_ISR1);
	if (res)
		goto out;

	res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
	if (res)
		goto out;
	/*
	 * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG.
	 * only one (ALARM or RTC) interrupt source may be enabled
	 * at time, we also could check our results
	 * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM]
	 */
	if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
		events |= RTC_IRQF | RTC_AF;
	else
		events |= RTC_IRQF | RTC_UF;

	res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M,
				   REG_RTC_STATUS_REG);
	if (res)
		goto out;
	/*
	 * Workaround for strange behaviour with T2. Need to write into ISR 
	 * register one more time to clear the interrupt. Otherwise, the same
	 * RTC event generates 2 interrupts in a row.
	 * (no errata document available)
	 */
	res = twl4030_i2c_read_u8(TWL4030_MODULE_INT, &rd_reg, REG_PWR_ISR1);
	if (res)
		goto out;

	rd_reg |= PWR_RTC_INT_CLR;
	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, rd_reg, REG_PWR_ISR1);
	if (res)
		goto out;

	/* Notify RTC core on event */
	rtc_update_irq(rtc, 1, events);

	ret = IRQ_HANDLED;
out:
	return ret;
}