Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-elphel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
linux-elphel
Commits
f5b08ac7
Commit
f5b08ac7
authored
Jul 30, 2019
by
Oleg Dzhimiev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
updated driver to current version, added our fall-through
parent
27a7df33
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
248 additions
and
118 deletions
+248
-118
rtc-m41t80.c
src/drivers/rtc/rtc-m41t80.c
+248
-118
No files found.
src/drivers/rtc/rtc-m41t80.c
View file @
f5b08ac7
...
@@ -16,10 +16,12 @@
...
@@ -16,10 +16,12 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bcd.h>
#include <linux/bcd.h>
#include <linux/clk-provider.h>
#include <linux/i2c.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/rtc.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/mutex.h>
...
@@ -52,6 +54,8 @@
...
@@ -52,6 +54,8 @@
#define M41T80_ALARM_REG_SIZE \
#define M41T80_ALARM_REG_SIZE \
(M41T80_REG_ALARM_SEC + 1 - M41T80_REG_ALARM_MON)
(M41T80_REG_ALARM_SEC + 1 - M41T80_REG_ALARM_MON)
#define M41T80_SQW_MAX_FREQ 32768
#define M41T80_SEC_ST BIT(7)
/* ST: Stop Bit */
#define M41T80_SEC_ST BIT(7)
/* ST: Stop Bit */
#define M41T80_ALMON_AFE BIT(7)
/* AFE: AF Enable Bit */
#define M41T80_ALMON_AFE BIT(7)
/* AFE: AF Enable Bit */
#define M41T80_ALMON_SQWE BIT(6)
/* SQWE: SQW Enable Bit */
#define M41T80_ALMON_SQWE BIT(6)
/* SQWE: SQW Enable Bit */
...
@@ -86,9 +90,71 @@ static const struct i2c_device_id m41t80_id[] = {
...
@@ -86,9 +90,71 @@ static const struct i2c_device_id m41t80_id[] = {
};
};
MODULE_DEVICE_TABLE
(
i2c
,
m41t80_id
);
MODULE_DEVICE_TABLE
(
i2c
,
m41t80_id
);
static
const
struct
of_device_id
m41t80_of_match
[]
=
{
{
.
compatible
=
"st,m41t62"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_SQ
|
M41T80_FEATURE_SQ_ALT
)
},
{
.
compatible
=
"st,m41t65"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_HT
|
M41T80_FEATURE_WD
)
},
{
.
compatible
=
"st,m41t80"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_SQ
)
},
{
.
compatible
=
"st,m41t81"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_HT
|
M41T80_FEATURE_SQ
)
},
{
.
compatible
=
"st,m41t81s"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_HT
|
M41T80_FEATURE_BL
|
M41T80_FEATURE_SQ
)
},
{
.
compatible
=
"st,m41t82"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_HT
|
M41T80_FEATURE_BL
|
M41T80_FEATURE_SQ
)
},
{
.
compatible
=
"st,m41t83"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_HT
|
M41T80_FEATURE_BL
|
M41T80_FEATURE_SQ
)
},
{
.
compatible
=
"st,m41t84"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_HT
|
M41T80_FEATURE_BL
|
M41T80_FEATURE_SQ
)
},
{
.
compatible
=
"st,m41t85"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_HT
|
M41T80_FEATURE_BL
|
M41T80_FEATURE_SQ
)
},
{
.
compatible
=
"st,m41t87"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_HT
|
M41T80_FEATURE_BL
|
M41T80_FEATURE_SQ
)
},
{
.
compatible
=
"microcrystal,rv4162"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_SQ
|
M41T80_FEATURE_WD
|
M41T80_FEATURE_SQ_ALT
)
},
/* DT compatibility only, do not use compatibles below: */
{
.
compatible
=
"st,rv4162"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_SQ
|
M41T80_FEATURE_WD
|
M41T80_FEATURE_SQ_ALT
)
},
{
.
compatible
=
"rv4162"
,
.
data
=
(
void
*
)(
M41T80_FEATURE_SQ
|
M41T80_FEATURE_WD
|
M41T80_FEATURE_SQ_ALT
)
},
{
}
};
MODULE_DEVICE_TABLE
(
of
,
m41t80_of_match
);
struct
m41t80_data
{
struct
m41t80_data
{
u8
features
;
unsigned
long
features
;
struct
i2c_client
*
client
;
struct
rtc_device
*
rtc
;
struct
rtc_device
*
rtc
;
#ifdef CONFIG_COMMON_CLK
struct
clk_hw
sqw
;
#endif
};
};
static
irqreturn_t
m41t80_handle_irq
(
int
irq
,
void
*
dev_id
)
static
irqreturn_t
m41t80_handle_irq
(
int
irq
,
void
*
dev_id
)
...
@@ -142,7 +208,7 @@ static int m41t80_get_datetime(struct i2c_client *client,
...
@@ -142,7 +208,7 @@ static int m41t80_get_datetime(struct i2c_client *client,
return
flags
;
return
flags
;
if
(
flags
&
M41T80_FLAGS_OF
)
{
if
(
flags
&
M41T80_FLAGS_OF
)
{
dev_err
(
&
client
->
dev
,
"Oscillator failure, data
might be
invalid. Elphel: proceeding anyway.
\n
"
);
dev_err
(
&
client
->
dev
,
"Oscillator failure, data
is
invalid. Elphel: proceeding anyway.
\n
"
);
//return -EINVAL;
//return -EINVAL;
}
}
...
@@ -168,6 +234,7 @@ static int m41t80_get_datetime(struct i2c_client *client,
...
@@ -168,6 +234,7 @@ static int m41t80_get_datetime(struct i2c_client *client,
/* Sets the given date and time to the real time clock. */
/* Sets the given date and time to the real time clock. */
static
int
m41t80_set_datetime
(
struct
i2c_client
*
client
,
struct
rtc_time
*
tm
)
static
int
m41t80_set_datetime
(
struct
i2c_client
*
client
,
struct
rtc_time
*
tm
)
{
{
struct
m41t80_data
*
clientdata
=
i2c_get_clientdata
(
client
);
unsigned
char
buf
[
8
];
unsigned
char
buf
[
8
];
int
err
,
flags
;
int
err
,
flags
;
...
@@ -183,6 +250,17 @@ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
...
@@ -183,6 +250,17 @@ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
buf
[
M41T80_REG_YEAR
]
=
bin2bcd
(
tm
->
tm_year
-
100
);
buf
[
M41T80_REG_YEAR
]
=
bin2bcd
(
tm
->
tm_year
-
100
);
buf
[
M41T80_REG_WDAY
]
=
tm
->
tm_wday
;
buf
[
M41T80_REG_WDAY
]
=
tm
->
tm_wday
;
/* If the square wave output is controlled in the weekday register */
if
(
clientdata
->
features
&
M41T80_FEATURE_SQ_ALT
)
{
int
val
;
val
=
i2c_smbus_read_byte_data
(
client
,
M41T80_REG_WDAY
);
if
(
val
<
0
)
return
val
;
buf
[
M41T80_REG_WDAY
]
|=
(
val
&
0xf0
);
}
err
=
i2c_smbus_write_i2c_block_data
(
client
,
M41T80_REG_SSEC
,
err
=
i2c_smbus_write_i2c_block_data
(
client
,
M41T80_REG_SSEC
,
sizeof
(
buf
),
buf
);
sizeof
(
buf
),
buf
);
if
(
err
<
0
)
{
if
(
err
<
0
)
{
...
@@ -273,6 +351,9 @@ static int m41t80_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
...
@@ -273,6 +351,9 @@ static int m41t80_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return
err
;
return
err
;
}
}
/* Keep SQWE bit value */
alarmvals
[
0
]
|=
(
ret
&
M41T80_ALMON_SQWE
);
ret
=
i2c_smbus_read_byte_data
(
client
,
M41T80_REG_FLAGS
);
ret
=
i2c_smbus_read_byte_data
(
client
,
M41T80_REG_FLAGS
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
...
@@ -359,116 +440,166 @@ static int m41t80_resume(struct device *dev)
...
@@ -359,116 +440,166 @@ static int m41t80_resume(struct device *dev)
static
SIMPLE_DEV_PM_OPS
(
m41t80_pm
,
m41t80_suspend
,
m41t80_resume
);
static
SIMPLE_DEV_PM_OPS
(
m41t80_pm
,
m41t80_suspend
,
m41t80_resume
);
static
ssize_t
flags_show
(
struct
device
*
dev
,
#ifdef CONFIG_COMMON_CLK
struct
device_attribute
*
attr
,
char
*
buf
)
#define sqw_to_m41t80_data(_hw) container_of(_hw, struct m41t80_data, sqw)
static
unsigned
long
m41t80_sqw_recalc_rate
(
struct
clk_hw
*
hw
,
unsigned
long
parent_rate
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
m41t80_data
*
m41t80
=
sqw_to_m41t80_data
(
hw
);
int
val
;
struct
i2c_client
*
client
=
m41t80
->
client
;
int
reg_sqw
=
(
m41t80
->
features
&
M41T80_FEATURE_SQ_ALT
)
?
M41T80_REG_WDAY
:
M41T80_REG_SQW
;
int
ret
=
i2c_smbus_read_byte_data
(
client
,
reg_sqw
);
unsigned
long
val
=
M41T80_SQW_MAX_FREQ
;
if
(
ret
<
0
)
return
0
;
val
=
i2c_smbus_read_byte_data
(
client
,
M41T80_REG_FLAGS
);
ret
>>=
4
;
if
(
val
<
0
)
if
(
ret
==
0
)
return
val
;
val
=
0
;
return
sprintf
(
buf
,
"%#x
\n
"
,
val
);
else
if
(
ret
>
1
)
val
=
val
/
(
1
<<
ret
);
return
val
;
}
}
static
DEVICE_ATTR_RO
(
flags
);
static
ssize_t
sqwfreq_show
(
struct
device
*
dev
,
static
long
m41t80_sqw_round_rate
(
struct
clk_hw
*
hw
,
unsigned
long
rate
,
struct
device_attribute
*
attr
,
char
*
buf
)
unsigned
long
*
prate
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
int
i
,
freq
=
M41T80_SQW_MAX_FREQ
;
struct
m41t80_data
*
clientdata
=
i2c_get_clientdata
(
client
);
int
val
,
reg_sqw
;
if
(
!
(
clientdata
->
features
&
M41T80_FEATURE_SQ
)
)
if
(
freq
<=
rate
)
return
-
EINVAL
;
return
freq
;
reg_sqw
=
M41T80_REG_SQW
;
for
(
i
=
2
;
i
<=
ilog2
(
M41T80_SQW_MAX_FREQ
);
i
++
)
{
if
(
clientdata
->
features
&
M41T80_FEATURE_SQ_ALT
)
freq
/=
1
<<
i
;
reg_sqw
=
M41T80_REG_WDAY
;
if
(
freq
<=
rate
)
val
=
i2c_smbus_read_byte_data
(
client
,
reg_sqw
);
return
freq
;
if
(
val
<
0
)
return
val
;
val
=
(
val
>>
4
)
&
0xf
;
switch
(
val
)
{
case
0
:
break
;
case
1
:
val
=
32768
;
break
;
default:
val
=
32768
>>
val
;
}
}
return
sprintf
(
buf
,
"%d
\n
"
,
val
);
return
0
;
}
}
static
ssize_t
sqwfreq_store
(
struct
device
*
dev
,
static
int
m41t80_sqw_set_rate
(
struct
clk_hw
*
hw
,
unsigned
long
rate
,
struct
device_attribute
*
attr
,
unsigned
long
parent_rate
)
const
char
*
buf
,
size_t
count
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
m41t80_data
*
m41t80
=
sqw_to_m41t80_data
(
hw
);
struct
m41t80_data
*
clientdata
=
i2c_get_clientdata
(
client
);
struct
i2c_client
*
client
=
m41t80
->
client
;
int
almon
,
sqw
,
reg_sqw
,
rc
;
int
reg_sqw
=
(
m41t80
->
features
&
M41T80_FEATURE_SQ_ALT
)
?
unsigned
long
val
;
M41T80_REG_WDAY
:
M41T80_REG_SQW
;
int
reg
,
ret
,
val
=
0
;
rc
=
kstrtoul
(
buf
,
0
,
&
val
);
if
(
rc
<
0
)
if
(
rate
)
{
return
rc
;
if
(
!
is_power_of_2
(
rate
))
if
(
!
(
clientdata
->
features
&
M41T80_FEATURE_SQ
))
return
-
EINVAL
;
if
(
val
)
{
if
(
!
is_power_of_2
(
val
))
return
-
EINVAL
;
return
-
EINVAL
;
val
=
ilog2
(
val
);
val
=
ilog2
(
rate
);
if
(
val
==
15
)
if
(
val
==
ilog2
(
M41T80_SQW_MAX_FREQ
)
)
val
=
1
;
val
=
1
;
else
if
(
val
<
14
)
else
if
(
val
<
(
ilog2
(
M41T80_SQW_MAX_FREQ
)
-
1
)
)
val
=
15
-
val
;
val
=
ilog2
(
M41T80_SQW_MAX_FREQ
)
-
val
;
else
else
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/* disable SQW, set SQW frequency & re-enable */
almon
=
i2c_smbus_read_byte_data
(
client
,
M41T80_REG_ALARM_MON
);
if
(
almon
<
0
)
return
almon
;
reg_sqw
=
M41T80_REG_SQW
;
if
(
clientdata
->
features
&
M41T80_FEATURE_SQ_ALT
)
reg_sqw
=
M41T80_REG_WDAY
;
sqw
=
i2c_smbus_read_byte_data
(
client
,
reg_sqw
);
if
(
sqw
<
0
)
return
sqw
;
sqw
=
(
sqw
&
0x0f
)
|
(
val
<<
4
);
rc
=
i2c_smbus_write_byte_data
(
client
,
M41T80_REG_ALARM_MON
,
almon
&
~
M41T80_ALMON_SQWE
);
if
(
rc
<
0
)
return
rc
;
if
(
val
)
{
reg
=
i2c_smbus_read_byte_data
(
client
,
reg_sqw
);
rc
=
i2c_smbus_write_byte_data
(
client
,
reg_sqw
,
sqw
);
if
(
reg
<
0
)
if
(
rc
<
0
)
return
reg
;
return
rc
;
rc
=
i2c_smbus_write_byte_data
(
client
,
M41T80_REG_ALARM_MON
,
reg
=
(
reg
&
0x0f
)
|
(
val
<<
4
);
almon
|
M41T80_ALMON_SQWE
);
if
(
rc
<
0
)
ret
=
i2c_smbus_write_byte_data
(
client
,
reg_sqw
,
reg
);
return
rc
;
if
(
ret
<
0
)
}
return
ret
;
return
count
;
return
-
EINVAL
;
}
}
static
DEVICE_ATTR_RW
(
sqwfreq
);
static
struct
attribute
*
attrs
[]
=
{
static
int
m41t80_sqw_control
(
struct
clk_hw
*
hw
,
bool
enable
)
&
dev_attr_flags
.
attr
,
{
&
dev_attr_sqwfreq
.
attr
,
struct
m41t80_data
*
m41t80
=
sqw_to_m41t80_data
(
hw
);
NULL
,
struct
i2c_client
*
client
=
m41t80
->
client
;
};
int
ret
=
i2c_smbus_read_byte_data
(
client
,
M41T80_REG_ALARM_MON
);
if
(
ret
<
0
)
return
ret
;
if
(
enable
)
ret
|=
M41T80_ALMON_SQWE
;
else
ret
&=
~
M41T80_ALMON_SQWE
;
static
struct
attribute_group
attr_group
=
{
return
i2c_smbus_write_byte_data
(
client
,
M41T80_REG_ALARM_MON
,
ret
);
.
attrs
=
attrs
,
}
static
int
m41t80_sqw_prepare
(
struct
clk_hw
*
hw
)
{
return
m41t80_sqw_control
(
hw
,
1
);
}
static
void
m41t80_sqw_unprepare
(
struct
clk_hw
*
hw
)
{
m41t80_sqw_control
(
hw
,
0
);
}
static
int
m41t80_sqw_is_prepared
(
struct
clk_hw
*
hw
)
{
struct
m41t80_data
*
m41t80
=
sqw_to_m41t80_data
(
hw
);
struct
i2c_client
*
client
=
m41t80
->
client
;
int
ret
=
i2c_smbus_read_byte_data
(
client
,
M41T80_REG_ALARM_MON
);
if
(
ret
<
0
)
return
ret
;
return
!!
(
ret
&
M41T80_ALMON_SQWE
);
}
static
const
struct
clk_ops
m41t80_sqw_ops
=
{
.
prepare
=
m41t80_sqw_prepare
,
.
unprepare
=
m41t80_sqw_unprepare
,
.
is_prepared
=
m41t80_sqw_is_prepared
,
.
recalc_rate
=
m41t80_sqw_recalc_rate
,
.
round_rate
=
m41t80_sqw_round_rate
,
.
set_rate
=
m41t80_sqw_set_rate
,
};
};
static
struct
clk
*
m41t80_sqw_register_clk
(
struct
m41t80_data
*
m41t80
)
{
struct
i2c_client
*
client
=
m41t80
->
client
;
struct
device_node
*
node
=
client
->
dev
.
of_node
;
struct
clk
*
clk
;
struct
clk_init_data
init
;
int
ret
;
/* First disable the clock */
ret
=
i2c_smbus_read_byte_data
(
client
,
M41T80_REG_ALARM_MON
);
if
(
ret
<
0
)
return
ERR_PTR
(
ret
);
ret
=
i2c_smbus_write_byte_data
(
client
,
M41T80_REG_ALARM_MON
,
ret
&
~
(
M41T80_ALMON_SQWE
));
if
(
ret
<
0
)
return
ERR_PTR
(
ret
);
init
.
name
=
"m41t80-sqw"
;
init
.
ops
=
&
m41t80_sqw_ops
;
init
.
flags
=
0
;
init
.
parent_names
=
NULL
;
init
.
num_parents
=
0
;
m41t80
->
sqw
.
init
=
&
init
;
/* optional override of the clockname */
of_property_read_string
(
node
,
"clock-output-names"
,
&
init
.
name
);
/* register the clock */
clk
=
clk_register
(
&
client
->
dev
,
&
m41t80
->
sqw
);
if
(
!
IS_ERR
(
clk
))
of_clk_add_provider
(
node
,
of_clk_src_simple_get
,
clk
);
return
clk
;
}
#endif
#ifdef CONFIG_RTC_DRV_M41T80_WDT
#ifdef CONFIG_RTC_DRV_M41T80_WDT
/*
/*
*****************************************************************************
*****************************************************************************
...
@@ -759,13 +890,6 @@ static struct notifier_block wdt_notifier = {
...
@@ -759,13 +890,6 @@ static struct notifier_block wdt_notifier = {
*****************************************************************************
*****************************************************************************
*/
*/
static
void
m41t80_remove_sysfs_group
(
void
*
_dev
)
{
struct
device
*
dev
=
_dev
;
sysfs_remove_group
(
&
dev
->
kobj
,
&
attr_group
);
}
static
int
m41t80_probe
(
struct
i2c_client
*
client
,
static
int
m41t80_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
id
)
const
struct
i2c_device_id
*
id
)
{
{
...
@@ -774,6 +898,7 @@ static int m41t80_probe(struct i2c_client *client,
...
@@ -774,6 +898,7 @@ static int m41t80_probe(struct i2c_client *client,
struct
rtc_device
*
rtc
=
NULL
;
struct
rtc_device
*
rtc
=
NULL
;
struct
rtc_time
tm
;
struct
rtc_time
tm
;
struct
m41t80_data
*
m41t80_data
=
NULL
;
struct
m41t80_data
*
m41t80_data
=
NULL
;
bool
wakeup_source
=
false
;
if
(
!
i2c_check_functionality
(
client
->
adapter
,
I2C_FUNC_SMBUS_I2C_BLOCK
|
if
(
!
i2c_check_functionality
(
client
->
adapter
,
I2C_FUNC_SMBUS_I2C_BLOCK
|
I2C_FUNC_SMBUS_BYTE_DATA
))
{
I2C_FUNC_SMBUS_BYTE_DATA
))
{
...
@@ -786,9 +911,18 @@ static int m41t80_probe(struct i2c_client *client,
...
@@ -786,9 +911,18 @@ static int m41t80_probe(struct i2c_client *client,
if
(
!
m41t80_data
)
if
(
!
m41t80_data
)
return
-
ENOMEM
;
return
-
ENOMEM
;
m41t80_data
->
features
=
id
->
driver_data
;
m41t80_data
->
client
=
client
;
if
(
client
->
dev
.
of_node
)
m41t80_data
->
features
=
(
unsigned
long
)
of_device_get_match_data
(
&
client
->
dev
);
else
m41t80_data
->
features
=
id
->
driver_data
;
i2c_set_clientdata
(
client
,
m41t80_data
);
i2c_set_clientdata
(
client
,
m41t80_data
);
#ifdef CONFIG_OF
wakeup_source
=
of_property_read_bool
(
client
->
dev
.
of_node
,
"wakeup-source"
);
#endif
if
(
client
->
irq
>
0
)
{
if
(
client
->
irq
>
0
)
{
rc
=
devm_request_threaded_irq
(
&
client
->
dev
,
client
->
irq
,
rc
=
devm_request_threaded_irq
(
&
client
->
dev
,
client
->
irq
,
NULL
,
m41t80_handle_irq
,
NULL
,
m41t80_handle_irq
,
...
@@ -797,14 +931,16 @@ static int m41t80_probe(struct i2c_client *client,
...
@@ -797,14 +931,16 @@ static int m41t80_probe(struct i2c_client *client,
if
(
rc
)
{
if
(
rc
)
{
dev_warn
(
&
client
->
dev
,
"unable to request IRQ, alarms disabled
\n
"
);
dev_warn
(
&
client
->
dev
,
"unable to request IRQ, alarms disabled
\n
"
);
client
->
irq
=
0
;
client
->
irq
=
0
;
}
else
{
wakeup_source
=
false
;
m41t80_rtc_ops
.
read_alarm
=
m41t80_read_alarm
;
m41t80_rtc_ops
.
set_alarm
=
m41t80_set_alarm
;
m41t80_rtc_ops
.
alarm_irq_enable
=
m41t80_alarm_irq_enable
;
/* Enable the wakealarm */
device_init_wakeup
(
&
client
->
dev
,
true
);
}
}
}
}
if
(
client
->
irq
>
0
||
wakeup_source
)
{
m41t80_rtc_ops
.
read_alarm
=
m41t80_read_alarm
;
m41t80_rtc_ops
.
set_alarm
=
m41t80_set_alarm
;
m41t80_rtc_ops
.
alarm_irq_enable
=
m41t80_alarm_irq_enable
;
/* Enable the wakealarm */
device_init_wakeup
(
&
client
->
dev
,
true
);
}
rtc
=
devm_rtc_device_register
(
&
client
->
dev
,
client
->
name
,
rtc
=
devm_rtc_device_register
(
&
client
->
dev
,
client
->
name
,
&
m41t80_rtc_ops
,
THIS_MODULE
);
&
m41t80_rtc_ops
,
THIS_MODULE
);
...
@@ -812,6 +948,10 @@ static int m41t80_probe(struct i2c_client *client,
...
@@ -812,6 +948,10 @@ static int m41t80_probe(struct i2c_client *client,
return
PTR_ERR
(
rtc
);
return
PTR_ERR
(
rtc
);
m41t80_data
->
rtc
=
rtc
;
m41t80_data
->
rtc
=
rtc
;
if
(
client
->
irq
<=
0
)
{
/* We cannot support UIE mode if we do not have an IRQ line */
rtc
->
uie_unsupported
=
1
;
}
/* Make sure HT (Halt Update) bit is cleared */
/* Make sure HT (Halt Update) bit is cleared */
rc
=
i2c_smbus_read_byte_data
(
client
,
M41T80_REG_ALARM_HOUR
);
rc
=
i2c_smbus_read_byte_data
(
client
,
M41T80_REG_ALARM_HOUR
);
...
@@ -846,21 +986,6 @@ static int m41t80_probe(struct i2c_client *client,
...
@@ -846,21 +986,6 @@ static int m41t80_probe(struct i2c_client *client,
return
rc
;
return
rc
;
}
}
/* Export sysfs entries */
rc
=
sysfs_create_group
(
&
(
&
client
->
dev
)
->
kobj
,
&
attr_group
);
if
(
rc
)
{
dev_err
(
&
client
->
dev
,
"Failed to create sysfs group: %d
\n
"
,
rc
);
return
rc
;
}
rc
=
devm_add_action_or_reset
(
&
client
->
dev
,
m41t80_remove_sysfs_group
,
&
client
->
dev
);
if
(
rc
)
{
dev_err
(
&
client
->
dev
,
"Failed to add sysfs cleanup action: %d
\n
"
,
rc
);
return
rc
;
}
#ifdef CONFIG_RTC_DRV_M41T80_WDT
#ifdef CONFIG_RTC_DRV_M41T80_WDT
if
(
m41t80_data
->
features
&
M41T80_FEATURE_HT
)
{
if
(
m41t80_data
->
features
&
M41T80_FEATURE_HT
)
{
save_client
=
client
;
save_client
=
client
;
...
@@ -873,6 +998,10 @@ static int m41t80_probe(struct i2c_client *client,
...
@@ -873,6 +998,10 @@ static int m41t80_probe(struct i2c_client *client,
return
rc
;
return
rc
;
}
}
}
}
#endif
#ifdef CONFIG_COMMON_CLK
if
(
m41t80_data
->
features
&
M41T80_FEATURE_SQ
)
m41t80_sqw_register_clk
(
m41t80_data
);
#endif
#endif
return
0
;
return
0
;
}
}
...
@@ -894,6 +1023,7 @@ static int m41t80_remove(struct i2c_client *client)
...
@@ -894,6 +1023,7 @@ static int m41t80_remove(struct i2c_client *client)
static
struct
i2c_driver
m41t80_driver
=
{
static
struct
i2c_driver
m41t80_driver
=
{
.
driver
=
{
.
driver
=
{
.
name
=
"rtc-m41t80"
,
.
name
=
"rtc-m41t80"
,
.
of_match_table
=
of_match_ptr
(
m41t80_of_match
),
.
pm
=
&
m41t80_pm
,
.
pm
=
&
m41t80_pm
,
},
},
.
probe
=
m41t80_probe
,
.
probe
=
m41t80_probe
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment