rtc: ds1307: add offset sysfs for mt41txx chips.
m41txx chips can hold a calibration value to get correct clock bias. Add offset handling (ranging between -63ppm and 126ppm) via sysfs. Signed-off-by: Giulio Benetti <giulio.benetti@micronovasrl.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
parent
1b4c794fda
commit
79230ff641
|
@ -114,6 +114,20 @@ enum ds_type {
|
||||||
# define RX8025_BIT_VDET 0x40
|
# define RX8025_BIT_VDET 0x40
|
||||||
# define RX8025_BIT_XST 0x20
|
# define RX8025_BIT_XST 0x20
|
||||||
|
|
||||||
|
#define M41TXX_REG_CONTROL 0x07
|
||||||
|
# define M41TXX_BIT_OUT BIT(7)
|
||||||
|
# define M41TXX_BIT_FT BIT(6)
|
||||||
|
# define M41TXX_BIT_CALIB_SIGN BIT(5)
|
||||||
|
# define M41TXX_M_CALIBRATION GENMASK(4, 0)
|
||||||
|
|
||||||
|
/* negative offset step is -2.034ppm */
|
||||||
|
#define M41TXX_NEG_OFFSET_STEP_PPB 2034
|
||||||
|
/* positive offset step is +4.068ppm */
|
||||||
|
#define M41TXX_POS_OFFSET_STEP_PPB 4068
|
||||||
|
/* Min and max values supported with 'offset' interface by M41TXX */
|
||||||
|
#define M41TXX_MIN_OFFSET ((-31) * M41TXX_NEG_OFFSET_STEP_PPB)
|
||||||
|
#define M41TXX_MAX_OFFSET ((31) * M41TXX_POS_OFFSET_STEP_PPB)
|
||||||
|
|
||||||
struct ds1307 {
|
struct ds1307 {
|
||||||
enum ds_type type;
|
enum ds_type type;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -146,6 +160,9 @@ struct chip_desc {
|
||||||
|
|
||||||
static int ds1307_get_time(struct device *dev, struct rtc_time *t);
|
static int ds1307_get_time(struct device *dev, struct rtc_time *t);
|
||||||
static int ds1307_set_time(struct device *dev, struct rtc_time *t);
|
static int ds1307_set_time(struct device *dev, struct rtc_time *t);
|
||||||
|
static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t);
|
||||||
|
static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t);
|
||||||
|
static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled);
|
||||||
static u8 do_trickle_setup_ds1339(struct ds1307 *, u32 ohms, bool diode);
|
static u8 do_trickle_setup_ds1339(struct ds1307 *, u32 ohms, bool diode);
|
||||||
static irqreturn_t rx8130_irq(int irq, void *dev_id);
|
static irqreturn_t rx8130_irq(int irq, void *dev_id);
|
||||||
static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t);
|
static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t);
|
||||||
|
@ -155,6 +172,8 @@ static irqreturn_t mcp794xx_irq(int irq, void *dev_id);
|
||||||
static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t);
|
static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t);
|
||||||
static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t);
|
static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t);
|
||||||
static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled);
|
static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled);
|
||||||
|
static int m41txx_rtc_read_offset(struct device *dev, long *offset);
|
||||||
|
static int m41txx_rtc_set_offset(struct device *dev, long offset);
|
||||||
|
|
||||||
static const struct rtc_class_ops rx8130_rtc_ops = {
|
static const struct rtc_class_ops rx8130_rtc_ops = {
|
||||||
.read_time = ds1307_get_time,
|
.read_time = ds1307_get_time,
|
||||||
|
@ -172,6 +191,16 @@ static const struct rtc_class_ops mcp794xx_rtc_ops = {
|
||||||
.alarm_irq_enable = mcp794xx_alarm_irq_enable,
|
.alarm_irq_enable = mcp794xx_alarm_irq_enable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct rtc_class_ops m41txx_rtc_ops = {
|
||||||
|
.read_time = ds1307_get_time,
|
||||||
|
.set_time = ds1307_set_time,
|
||||||
|
.read_alarm = ds1337_read_alarm,
|
||||||
|
.set_alarm = ds1337_set_alarm,
|
||||||
|
.alarm_irq_enable = ds1307_alarm_irq_enable,
|
||||||
|
.read_offset = m41txx_rtc_read_offset,
|
||||||
|
.set_offset = m41txx_rtc_set_offset,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct chip_desc chips[last_ds_type] = {
|
static const struct chip_desc chips[last_ds_type] = {
|
||||||
[ds_1307] = {
|
[ds_1307] = {
|
||||||
.nvram_offset = 8,
|
.nvram_offset = 8,
|
||||||
|
@ -228,10 +257,17 @@ static const struct chip_desc chips[last_ds_type] = {
|
||||||
.irq_handler = rx8130_irq,
|
.irq_handler = rx8130_irq,
|
||||||
.rtc_ops = &rx8130_rtc_ops,
|
.rtc_ops = &rx8130_rtc_ops,
|
||||||
},
|
},
|
||||||
|
[m41t0] = {
|
||||||
|
.rtc_ops = &m41txx_rtc_ops,
|
||||||
|
},
|
||||||
|
[m41t00] = {
|
||||||
|
.rtc_ops = &m41txx_rtc_ops,
|
||||||
|
},
|
||||||
[m41t11] = {
|
[m41t11] = {
|
||||||
/* this is battery backed SRAM */
|
/* this is battery backed SRAM */
|
||||||
.nvram_offset = 8,
|
.nvram_offset = 8,
|
||||||
.nvram_size = 56,
|
.nvram_size = 56,
|
||||||
|
.rtc_ops = &m41txx_rtc_ops,
|
||||||
},
|
},
|
||||||
[mcp794xx] = {
|
[mcp794xx] = {
|
||||||
.alarm = 1,
|
.alarm = 1,
|
||||||
|
@ -973,6 +1009,47 @@ static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||||
enabled ? MCP794XX_BIT_ALM0_EN : 0);
|
enabled ? MCP794XX_BIT_ALM0_EN : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int m41txx_rtc_read_offset(struct device *dev, long *offset)
|
||||||
|
{
|
||||||
|
struct ds1307 *ds1307 = dev_get_drvdata(dev);
|
||||||
|
unsigned int ctrl_reg;
|
||||||
|
u8 val;
|
||||||
|
|
||||||
|
regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg);
|
||||||
|
|
||||||
|
val = ctrl_reg & M41TXX_M_CALIBRATION;
|
||||||
|
|
||||||
|
/* check if positive */
|
||||||
|
if (ctrl_reg & M41TXX_BIT_CALIB_SIGN)
|
||||||
|
*offset = (val * M41TXX_POS_OFFSET_STEP_PPB);
|
||||||
|
else
|
||||||
|
*offset = -(val * M41TXX_NEG_OFFSET_STEP_PPB);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m41txx_rtc_set_offset(struct device *dev, long offset)
|
||||||
|
{
|
||||||
|
struct ds1307 *ds1307 = dev_get_drvdata(dev);
|
||||||
|
unsigned int ctrl_reg;
|
||||||
|
|
||||||
|
if ((offset < M41TXX_MIN_OFFSET) || (offset > M41TXX_MAX_OFFSET))
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
|
if (offset >= 0) {
|
||||||
|
ctrl_reg = DIV_ROUND_CLOSEST(offset,
|
||||||
|
M41TXX_POS_OFFSET_STEP_PPB);
|
||||||
|
ctrl_reg |= M41TXX_BIT_CALIB_SIGN;
|
||||||
|
} else {
|
||||||
|
ctrl_reg = DIV_ROUND_CLOSEST(abs(offset),
|
||||||
|
M41TXX_NEG_OFFSET_STEP_PPB);
|
||||||
|
}
|
||||||
|
|
||||||
|
return regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL,
|
||||||
|
M41TXX_M_CALIBRATION | M41TXX_BIT_CALIB_SIGN,
|
||||||
|
ctrl_reg);
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int ds1307_nvram_read(void *priv, unsigned int offset, void *val,
|
static int ds1307_nvram_read(void *priv, unsigned int offset, void *val,
|
||||||
|
|
Loading…
Reference in New Issue