staticint mcp795_stop_oscillator(struct device *dev, bool *extosc)
{ int retries = 5; int ret;
u8 data;
ret = mcp795_rtcc_set_bits(dev, MCP795_REG_SECONDS, MCP795_ST_BIT, 0); if (ret) return ret;
ret = mcp795_rtcc_read(dev, MCP795_REG_CONTROL, &data, 1); if (ret) return ret;
*extosc = !!(data & MCP795_EXTOSC_BIT);
ret = mcp795_rtcc_set_bits(
dev, MCP795_REG_CONTROL, MCP795_EXTOSC_BIT, 0); if (ret) return ret; /* wait for the OSCON bit to clear */ do {
usleep_range(700, 800);
ret = mcp795_rtcc_read(dev, MCP795_REG_DAY, &data, 1); if (ret) break; if (!(data & MCP795_OSCON_BIT)) break;
} while (--retries);
return !retries ? -EIO : ret;
}
staticint mcp795_start_oscillator(struct device *dev, bool *extosc)
{ if (extosc) {
u8 data = *extosc ? MCP795_EXTOSC_BIT : 0; int ret;
ret = mcp795_rtcc_set_bits(
dev, MCP795_REG_CONTROL, MCP795_EXTOSC_BIT, data); if (ret) return ret;
} return mcp795_rtcc_set_bits(
dev, MCP795_REG_SECONDS, MCP795_ST_BIT, MCP795_ST_BIT);
}
/* Enable or disable Alarm 0 in RTC */ staticint mcp795_update_alarm(struct device *dev, bool enable)
{ int ret;
/* Always write the date and month using a separate Write command. *Thisisaworkaroundforaknowsiliconissuethatsomecombinations *ofdateandmonthvaluesmayresultinthedatebeingresetto1.
*/
ret = mcp795_rtcc_write(dev, MCP795_REG_SECONDS, data, 5); if (ret) return ret;
ret = mcp795_rtcc_write(dev, MCP795_REG_MONTH, &data[5], 2); if (ret) return ret;
/* Start back RTC and restore previous value of EXTOSC bit. *ThereisnoneedtoclearEXTOSCbitwhenthepreviousvaluewas0 *becauseitwasalreadyclearedwhenstoppingtheRTCoscillator.
*/
ret = mcp795_start_oscillator(dev, extosc ? &extosc : NULL); if (ret) return ret;
/* Read current time from RTC hardware */
ret = mcp795_read_time(dev, &now_tm); if (ret) return ret; /* Get the number of seconds since 1970 */
now = rtc_tm_to_time64(&now_tm);
later = rtc_tm_to_time64(&alm->time); if (later <= now) return -EINVAL; /* make sure alarm fires within the next one year */ if ((later - now) >=
(SEC_PER_DAY * (365 + is_leap_year(alm->time.tm_year)))) return -EDOM; /* disable alarm */
ret = mcp795_update_alarm(dev, false); if (ret) return ret; /* Read registers, so we can leave configuration bits untouched */
ret = mcp795_rtcc_read(dev, MCP795_REG_ALM0_SECONDS, tmp, sizeof(tmp)); if (ret) return ret;
staticint mcp795_probe(struct spi_device *spi)
{ struct rtc_device *rtc; int ret;
spi->mode = SPI_MODE_0;
spi->bits_per_word = 8;
ret = spi_setup(spi); if (ret) {
dev_err(&spi->dev, "Unable to setup SPI\n"); return ret;
}
/* Start the oscillator but don't set the value of EXTOSC bit */
mcp795_start_oscillator(&spi->dev, NULL); /* Clear the 12 hour mode flag*/
mcp795_rtcc_set_bits(&spi->dev, 0x03, MCP795_24_BIT, 0);
rtc = devm_rtc_device_register(&spi->dev, "rtc-mcp795",
&mcp795_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc);
spi_set_drvdata(spi, rtc);
if (spi->irq > 0) {
dev_dbg(&spi->dev, "Alarm support enabled\n");
/* Clear any pending alarm (ALM0IF bit) before requesting *theinterrupt.
*/
mcp795_rtcc_set_bits(&spi->dev, MCP795_REG_ALM0_DAY,
MCP795_ALM0IF_BIT, 0);
ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
mcp795_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
dev_name(&rtc->dev), spi); if (ret)
dev_err(&spi->dev, "Failed to request IRQ: %d: %d\n",
spi->irq, ret); else
device_init_wakeup(&spi->dev, true);
} return0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.