EDA365电子工程师网
标题: 【问题】4412开发板配置pcf8563时钟芯片驱动后,无法使用,是什么问题呢? [打印本页]
作者: 独孤九剑17 时间: 2017-8-28 15:31
标题: 【问题】4412开发板配置pcf8563时钟芯片驱动后,无法使用,是什么问题呢?
c% X9 V# f' V" D1 x- Q! Z1 O
开发板:
各位版主、工程师们你们好:
请教你们一些问题:
(1)在内核中配置pcf8563时钟芯片启动完成,内核启动后 /dev/rtc/ 中没有pcf8563芯片对应的 rtc 节点;
(2)内核启动过程中打印 drivers/rtc/hctosys.c: unable to open rtc device (rtc0);
(3)pcf8563芯片驱动程序的 pcf8563_probe()在整个启动过程中没有被执行;
(4)请问这是怎么回事?该怎么修改???
(5)驱动程序代码如下:
驱动代码:# i. L0 A& f7 p" i; ~
#include <linux/i2c.h>
* M8 p3 E% H: G#include <linux/bcd.h>2 N$ e# O$ v5 d2 l' E+ I
#include <linux/rtc.h>
8 E3 l4 I1 M% Z#include <linux/slab.h>5 H4 u- @! E# I: Y: [
. t1 r8 [9 z$ |% x2 L! a6 {/ z- O#define DRV_VERSION "0.4.3". ]* r8 J! O9 a, R
1 r8 Z4 O0 q" q* x1 n7 K( t
#define PCF8563_REG_ST1 0x00 /* status */
1 {# |1 ^3 \/ @! p t! u#define PCF8563_REG_ST2 0x01
% S! U) G! v; s- F0 \* ^
4 a C* v5 S" K8 _: w: A5 {3 y+ w#define PCF8563_REG_SC 0x02 /* datetime */
% C2 K5 u: {1 e: J5 m; l#define PCF8563_REG_MN 0x03; J: X# }9 L+ V* ~
#define PCF8563_REG_HR 0x04
" O* F1 o# k: L+ z#define PCF8563_REG_DM 0x05
8 V0 X P! Q4 p3 G& j#define PCF8563_REG_DW 0x06
' r$ `" _* ]& u1 L. B7 i0 u$ A#define PCF8563_REG_MO 0x070 W- h4 m) j9 \ w8 R
#define PCF8563_REG_YR 0x08+ N( g: R- K$ Y' Z" r; Z) E
/ X4 H! {. _$ n( r) `. V#define PCF8563_REG_AMN 0x09 /* alarm */
; H5 A8 q9 V3 p; |$ I. ?! V#define PCF8563_REG_AHR 0x0A3 E1 i4 c0 D( a: T+ E$ j
#define PCF8563_REG_ADM 0x0B; T- x$ b+ E* C3 D/ k9 P7 l& X
#define PCF8563_REG_ADW 0x0C
1 f" Y& Z, Y; {/ @: o9 W' w3 _
( x, a0 x: |) _& g/ l3 [6 s#define PCF8563_REG_CLKO 0x0D /* clock out *// B7 E, `3 s. g3 Z% V+ Q
#define PCF8563_REG_TMRC 0x0E /* timer control */
7 r* N4 O i, R S) H' K0 e#define PCF8563_REG_TMR 0x0F /* timer */5 p/ l% S7 I" s0 a3 C9 `4 U
8 d, \3 m- ^3 u3 f* c8 E$ K; l#define PCF8563_SC_LV 0x80 /* low voltage */
0 _/ j/ F3 {+ Z#define PCF8563_MO_C 0x80 /* century */, @/ c( t/ N8 S" ~9 y8 O/ c' }
$ N- G: h1 x/ R; @, sstatic struct i2c_driver pcf8563_driver;
& j% K2 b' F8 N
2 F) L7 e7 Y7 A, U/ u' I6 vstruct pcf8563 {
, i& C% b# }8 E5 R struct rtc_device *rtc;7 L7 T0 X: r% o6 t
/** |# P$ V2 x( z6 Y4 ?- {
* The meaning of MO_C bit varies by the chip type.
5 e, Q3 z v0 l, ~& l" r4 s * From PCF8563 datasheet: this bit is toggled when the years* O+ }4 Z' M+ }- {% ]/ w+ z7 J9 I
* register overflows from 99 to 00
1 y1 X' U9 y' f3 P+ ? h$ E0 G * 0 indicates the century is 20xx
U# y) s2 e- i+ j5 u2 ~$ D6 B * 1 indicates the century is 19xx# G) V( r) X; n$ q; v
* From RTC8564 datasheet: this bit indicates change of4 G5 O9 [8 A9 c
* century. When the year digit data overflows from 99 to 00,, G' k( ^) W' {
* this bit is set. By presetting it to 0 while still in the
& M# e! g# [, n d9 [ * 20th century, it will be set in year 2000, ...
$ r. v3 I# c! g8 j' E' P * There seems no reliable way to know how the system use this/ T- ?" U% d6 _0 U
* bit. So let's do it heuristically, assuming we are live in* i [6 s, n0 w# M R, J. `- N
* 1970...2069.
. b, |2 B7 W& k& i G */" R: _. G+ ], l5 ^2 N
int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */2 U# K+ N0 s0 ?* F3 Q# D5 ^4 a
};
; W, V7 d4 e1 V$ [4 A v, p! L5 l) @# G! X n; M5 R7 V7 ~& u1 N
/*5 b3 ]; V3 U+ e' {
* In the routines that deal directly with the pcf8563 hardware, we use, G3 u. l2 M3 e
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
- r, P# n/ j) h' Q# z3 {*/: H' z/ l# \# p/ `3 n! v
static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)" \ A$ ]1 K# F( T4 q) f9 J
{/ O) ~: L% j+ x/ u7 t' s+ G
struct pcf8563 *pcf8563 = i2c_get_clientdata(client);1 {% O T& r' X$ n, Z' p
unsigned char buf[13] = { PCF8563_REG_ST1 };# q" U3 K7 r6 i9 h
4 |; H& a: @2 k& q. b
struct i2c_msg msgs[] = {+ W: {" ~; F3 E7 e9 V
{ client->addr, 0, 1, buf }, /* setup read ptr */* o8 Q/ r0 k! P
{ client->addr, I2C_M_RD, 13, buf }, /* read status + date */
7 E- p- h& b3 I+ @, ] };- s7 n6 Y' s) U% a
1 @' g1 e% Z [) g /* read registers */
8 B+ y$ o W o5 `' ~% h if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
7 }! P- R9 b) V( L/ l9 `6 l3 t dev_err(&client->dev, "%s: read error\n", __func__);
+ }0 G, J4 l+ L4 P! k$ M return -EIO;
7 ~4 U0 H4 N# G }$ d$ k3 d& K9 Z! m) C
" q" r( O2 m: S; P9 Q" ?6 k
if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)+ _5 T( Q5 C8 v! D# r# e
dev_info(&client->dev,
' J7 `" u9 U6 t4 e; {& ~! ]( d "low voltage detected, date/time is not reliable.\n");; u, r ]9 t3 `! |& ^5 h1 i
1 `! T* `1 Q% ]% c3 {% c4 {. M# Y+ L dev_dbg(&client->dev,
0 v5 o8 Y. A6 ^ j. C "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "- L1 N8 T( |: i3 E& U# B+ _
"mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
6 i A5 V& v, P' y! y2 A {, y __func__,4 b' z( P4 X3 N1 z& D
buf[0], buf[1], buf[2], buf[3],
9 ^" H) x$ v' W5 ?( c3 b; Y$ x" @) h buf[4], buf[5], buf[6], buf[7],: l4 A' M" k+ A( Y
buf[8]);5 ~) G& B5 R0 `3 V4 r% @. t9 h
% M' Z: o' _* ~% d% q2 c/ z- e; } n; E8 H
tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
$ z6 r* u+ x5 Z! p u& |* c tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
\/ V" Q7 Q2 t8 M" S/ [! y tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */1 U3 Y+ U y c4 g/ Z% y
tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
' G+ W- v& V* T. w" F' A+ i tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
; x7 h: m/ r$ J5 ?: J0 k5 S5 a8 h tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
$ _, \4 J0 z9 x' `% } W tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);6 ^$ B# T! ^% H6 q) ]& Z
if (tm->tm_year < 70)
3 A; Y8 B8 {- \ tm->tm_year += 100; /* assume we are in 1970...2069 */
: K8 ^# Z; k6 @) c /* detect the polarity heuristically. see note above. */! I3 Z& R7 a# Z! e2 ]8 n% x
pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?2 F- o' t; n( y$ z2 D' }8 N
(tm->tm_year >= 100) : (tm->tm_year < 100);
! `# Y- [' O8 K$ K
8 G; A) o% S- j dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "! q: z/ i* v- t; I5 n, [) \1 y0 t7 e( I
"mday=%d, mon=%d, year=%d, wday=%d\n",
9 P7 k6 l- X3 h4 `) _. x __func__,# h0 ]6 j# ^7 I" P8 @. F6 _
tm->tm_sec, tm->tm_min, tm->tm_hour,+ F' i# D, ?3 J# i
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
1 V! p! I4 [6 {7 y
7 H3 x0 M2 q) ?. G; q1 Q /* the clock can give out invalid datetime, but we cannot return
& U% G, R6 s; Y: `% `8 F8 A * -EINVAL otherwise hwclock will refuse to set the time on bootup.; S$ D, E& y# {% P4 {
*/
" \0 j9 m8 V$ l8 T1 g, C* e6 D7 O if (rtc_valid_tm(tm) < 0)4 E6 P* {( c: F$ h0 ~7 c
dev_err(&client->dev, "retrieved date/time is not valid.\n");
U, P2 P5 o- G# K
0 _, Y% E* P1 d+ L return 0;
3 u* I. n7 k; Y- `1 s}
* j% j+ u. @) \, P
# j$ ~0 Y, h$ Z6 ?/ }) R- bstatic int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)) l u4 H$ Q$ H; O, N j7 D7 d
{
0 _9 `! A: d* @, [. ]% i" F! c: e( X# r struct pcf8563 *pcf8563 = i2c_get_clientdata(client);1 m4 `* Y* o/ L" `- D& r
int i, err;
) X8 m2 A# V- B unsigned char buf[9];
( I7 J0 d5 G/ K5 _/ r* U5 _$ q. Y3 R# h
dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "3 W$ { e6 B3 t7 J9 [8 u
"mday=%d, mon=%d, year=%d, wday=%d\n",# {9 X8 o3 w% \4 U
__func__,
" p7 k% Y( o$ |2 i tm->tm_sec, tm->tm_min, tm->tm_hour,! U1 x$ v N; t
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
4 R7 }! _1 f) ?& m# M5 v3 J9 a
4 Q7 G, d/ L0 I" t /* hours, minutes and seconds */
5 S; i5 D1 ~* P( B& s buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);1 b8 j' F9 }; q8 P0 B( u* p5 `8 h
buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
2 x5 ^% m: o; Z* G6 x" U6 G buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);
: ? p( X7 x5 M+ C I; [
# J) |# w* N- g; Y) K buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);+ w1 K& H8 }) b! p( Q
( I! N0 l0 ~' `
/* month, 1 - 12 */
7 P8 `1 L) e! r* [- Y! ^; C W, ^ buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);4 r2 p/ J$ f; `* u9 b
9 y# r4 q+ d8 T% V /* year and century */( a7 [, B) y$ g( M9 D5 y6 K
buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
6 Q7 z4 j% i* m if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100)); Z; ]) n. }( R4 V8 i# H# m% m
buf[PCF8563_REG_MO] |= PCF8563_MO_C;
5 u( t. m1 C$ {# h: s7 \+ {
5 h$ E' s. Y" O- R+ _ buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
# A& v% K0 P- w- u. b- t( F1 n, m! m) {" b) m Z
/* write register's data */; y. F. J: a( j- h- ~
for (i = 0; i < 7; i++) {
. ?' v9 R9 m# q2 q" {( g unsigned char data[2] = { PCF8563_REG_SC + i,
1 O- N" D9 `7 e1 r& \# d. V6 M( ]$ R buf[PCF8563_REG_SC + i] };
5 c! f6 K# J- s" e3 L6 G# r2 D! i) ?* v; }; c
err = i2c_master_send(client, data, sizeof(data));0 V+ j) a/ @* e. K2 ~( v5 g( ^5 x
if (err != sizeof(data)) {+ |" l& ^: G# |2 O8 N: j5 `0 N6 K
dev_err(&client->dev,
- F$ Q: I" M* G) O* s "%s: err=%d addr=%02x, data=%02x\n",
_! r1 D! z6 a& g __func__, err, data[0], data[1]);
, A( x$ Z- K* ?6 s return -EIO;9 }. x0 ]' [" W' C6 [
}# s3 D' z& k$ W1 \2 z) W4 m. ~' G
};2 ]% g4 v. y, S- U# N
3 Z: a+ q; f# J( D W5 |% b1 Q! Z: z return 0;+ @# o, P" A; N& ?/ r
}& C5 n' V O9 E* G/ M/ p3 }
" |7 a1 a5 R3 ~# U- P% W( w0 D) Hstatic int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
; Q' c" ^0 V# _: ~& G# z, W0 i{# I' K1 p; n: o. ]4 ]
return pcf8563_get_datetime(to_i2c_client(dev), tm);' [+ l+ c1 l! Y% q. i
}
( p2 ]+ L3 ]- J
0 v7 x. e1 b5 Y' @2 C9 {/ H8 Bstatic int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) O9 K) _8 Y3 a- G% C4 ^
{% C, o V6 V+ _4 ]- x/ x; S
return pcf8563_set_datetime(to_i2c_client(dev), tm);. K8 ~& k" Q( O0 L4 ^% D
}) l' x3 o$ H2 C; @3 _" }) C
) s' P8 N0 }( pstatic const struct rtc_class_ops pcf8563_rtc_ops = {, b( I( B1 z8 G
.read_time = pcf8563_rtc_read_time,3 \9 J: n, X' W: I7 G
.set_time = pcf8563_rtc_set_time,
# ^4 X; {' c, a# H};6 J/ [- K2 U a
6 [2 N5 ?8 B4 P) |/ R: `static int pcf8563_probe(struct i2c_client *client,
% S+ v8 i/ ]! [; Z const struct i2c_device_id *id)
B: r# E4 G) }{3 N4 j2 u. m3 W; d2 d- I- Z
struct pcf8563 *pcf8563;
/ G- O, @ ^& Q- u3 G& ^2 u9 ?2 s* u- x. N9 ?0 \. a
int err = 0;
0 R- ~3 d" r j* s$ |! s5 ~ u3 T5 B e3 |. ^4 t+ n
dev_dbg(&client->dev, "%s\n", __func__);
4 l+ [6 Z: A, ~- s. _3 z
2 e s5 m4 @0 ]5 D3 Q. J7 V if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
9 D# i2 w \, U$ k return -ENODEV;
: B1 j; O) n6 Y4 J# M1 T P" Y9 N0 U% O5 Q
pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL);* x1 g0 O* H1 w' w
if (!pcf8563)
: l' c0 H4 m8 R$ c return -ENOMEM;
; M: f2 J7 L1 Q" }. B2 @0 i6 O3 C; E5 N
dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");+ x$ f4 Q) J3 ]" n* u: h
6 l% j, L; _# [3 d; ]
i2c_set_clientdata(client, pcf8563);* d; M; f$ j- o7 v. d/ t0 d
9 V r9 w1 H L, u
pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,: T+ ^+ I+ D( n/ P
&client->dev, &pcf8563_rtc_ops, THIS_MODULE);- t$ T( T# [4 J3 w; r0 b
1 g' S" d3 O. N5 _
if (IS_ERR(pcf8563->rtc)) {' L; T! N& p6 _; B
err = PTR_ERR(pcf8563->rtc);
; [2 A$ Z. ?8 [+ g goto exit_kfree;
4 n" q! ^# X6 z, d. [) l }( \$ d5 V, \- [4 I. V2 h: K
O& S3 O8 G8 i/ V+ M return 0;
- N4 q+ o4 {/ c" P1 O( Y& E) b+ L4 `' B+ Y
exit_kfree:
) q1 G, R) s2 c3 I* @ kfree(pcf8563);
+ {7 J4 d3 c4 I) p% k W0 \8 X2 N: m$ Q3 s! Q& ^% N; {4 L1 v
return err;
6 K J+ d: e% b7 x8 p}. L: P* Z; A: ? O
5 v/ p! i' Z9 K& R9 k: `
static int pcf8563_remove(struct i2c_client *client)
1 m; z. [# ?8 ^( j0 |{
/ Z" `5 ~6 @8 e$ x5 V9 h' n' u struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
- @2 H+ ?" k/ y* N" Z9 q* v/ K% q; b
if (pcf8563->rtc)0 `& x. [3 K* \5 g
rtc_device_unregister(pcf8563->rtc); x* Z u7 G8 r. d# b e+ V
' d! i* Y/ F; i, c! N/ Z4 r" y
kfree(pcf8563);
- H$ p, _7 k3 z6 r3 z4 P# J x5 e
return 0;9 |& R/ X, V8 X- i
}" d# P' q7 Z, D7 j( ^/ B) V- E
5 _: n% }+ l. W+ @7 M, @3 `% Ostatic const struct i2c_device_id pcf8563_id[] = {/ O- Q2 ]- V. v+ |4 ^7 W. L
{ "pcf8563", 0 },1 u# U ~( W9 O1 }& Q8 N$ ]3 d9 T
{ "rtc8564", 0 },
2 `, ?* g# V0 A' Y: }# ^+ x# Y { }
; `$ x( j- ?& |' g( s- _2 m* B};
# I# W: n, j5 g, O) n: UMODULE_DEVICE_TABLE(i2c, pcf8563_id);
" x. d* }% F. Y5 ]( N9 L; ?9 Q( Q# M" H9 B% P, z d: j% ~3 z
static struct i2c_driver pcf8563_driver = {
5 A/ G! V1 x% o9 d. t .driver = {
6 M; |6 S3 Q8 } .name = "rtc-pcf8563",' ?- p, x: p! Q4 V( @0 c, H
},
8 n& `0 E, T- T p6 m3 j% `5 n .probe = pcf8563_probe,
& b+ ]" f" D+ n8 M. E7 ^* G2 | .remove = pcf8563_remove,2 L; b! P" o. ~4 ~$ q4 `) a; r9 z" c5 T
.id_table = pcf8563_id,+ U$ U4 i- j7 Y/ l7 Q0 v; S) v1 b
};
7 q( y1 Z; V+ @, u9 P" i0 z" C& h" d5 ?/ r7 X
static int __init pcf8563_init(void)
& B. J4 G' b" L{
% H) o+ `6 j3 W& | return i2c_add_driver(&pcf8563_driver);# `( e4 o4 d* d; a' `5 ?) u* q6 I
}
* X6 |8 J! `5 h) C9 R5 [ K8 K) N' k R% c: l- H* n4 u
static void __exit pcf8563_exit(void)' u' R$ s, L! C7 ?5 Y' ?1 n) m; ^
{! Y; b# s" y/ n k
i2c_del_driver(&pcf8563_driver);
5 v% f @& [0 G8 ~8 j# t$ w& n' u5 Y}4 o- G2 Y0 X) x+ Q
0 l5 A. j0 y, X; o1 u( C" o$ Z0 H
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); I0 k, u; ^) E+ N3 V
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");- u8 { `) M1 V: X; C# \
MODULE_LICENSE("GPL");
4 @- h" b) d: v% K3 C+ j2 uMODULE_VERSION(DRV_VERSION);5 R* N3 |2 B H2 @ s0 j; o+ f
, b5 h5 E8 }3 W9 M4 B8 d0 l
module_init(pcf8563_init);% E* T, Q% [0 X& T& b k- i: R
module_exit(pcf8563_exit);
- u. h# `1 y3 @" y
作者: soku338 时间: 2017-11-24 10:47
这么一堆,看蒙了,不过还是了解一下下
作者: f__liu 时间: 2017-11-25 20:27
哪个正常的人能崇拜一只蟑螂呢?
欢迎光临 EDA365电子工程师网 (http://bbs.elecnest.cn/) |
Powered by Discuz! X3.2 |