找回密码
 注册
关于网站域名变更的通知
查看: 604|回复: 2
打印 上一主题 下一主题

【问题】4412开发板配置pcf8563时钟芯片驱动后,无法使用,是什么问题呢?

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2017-8-28 15:31 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x

$ Z9 Q) a* |6 q! g
开发板:
各位版主、工程师们你们好:
      请教你们一些问题:
             1)在内核中配置pcf8563时钟芯片启动完成,内核启动后 /dev/rtc/ 中没有pcf8563芯片对应的 rtc 节点;
             2)内核启动过程中打印 drivers/rtc/hctosys.c: unable to open rtc device (rtc0);
             3)pcf8563芯片驱动程序的 pcf8563_probe()在整个启动过程中没有被执行;
             4)请问这是怎么回事?该怎么修改???
             5)驱动程序代码如下:
驱动代码:
1 T+ C$ Y0 y6 K3 S# u4 J
#include <linux/i2c.h>4 N  z/ }- b% A; V8 \, a  M
#include <linux/bcd.h>- l& i) P  N; G. Y
#include <linux/rtc.h>' P, {9 p. g9 A! t( S  Y8 C
#include <linux/slab.h>
" G, R. v2 o; I4 d% L3 F" ], [7 V0 A

/ K+ p! |2 ?, B$ D7 P
#define DRV_VERSION "0.4.3"' [3 P% M" V/ S& K
+ u/ }8 L4 a/ R) `1 I
#define PCF8563_REG_ST1                0x00 /* status */
, F6 R$ [( G- s5 w/ n1 g9 W
#define PCF8563_REG_ST2                0x015 Z% V5 |8 f% L- k" D; v4 i0 c
8 r0 n& Q) ~5 O. w
#define PCF8563_REG_SC                0x02 /* datetime */
: E- u; L7 r# Y4 ?6 T
#define PCF8563_REG_MN                0x03. y- X5 y+ W3 L" q. u0 ]; d
#define PCF8563_REG_HR                0x04
. x& ^+ I9 F7 Y. O: \
#define PCF8563_REG_DM                0x05* l/ x  Z& o8 g3 m+ a
#define PCF8563_REG_DW                0x06- |; @* w  ?; x7 f. E: L
#define PCF8563_REG_MO                0x07- K+ o2 y7 A. M
#define PCF8563_REG_YR                0x08
5 v, i# u/ @0 \' A/ `
6 U2 K* N1 N( D! W, R
#define PCF8563_REG_AMN                0x09 /* alARM */8 n# h6 z9 t$ t* f$ E# {* }9 o7 v
#define PCF8563_REG_AHR                0x0A
! ]) t( ?$ \4 f- R, h
#define PCF8563_REG_ADM                0x0B' `3 Z; P/ w. @. q: o6 k# s5 V  \
#define PCF8563_REG_ADW                0x0C
" X+ O- f5 {4 }) }& _
, j4 R% r2 G1 V- O; w  P# N
#define PCF8563_REG_CLKO        0x0D /* clock out */2 H& I: u0 q+ Z& Q2 i
#define PCF8563_REG_TMRC        0x0E /* timer control */
! ]" B9 u3 v4 F% V4 h1 o) E! |
#define PCF8563_REG_TMR                0x0F /* timer */
$ G! s. M3 N: G' K* H

' `' m( i9 a( }. n' I
#define PCF8563_SC_LV                0x80 /* low voltage */" ?* ]( P4 U3 H. O$ {
#define PCF8563_MO_C                0x80 /* century */0 I7 r9 a/ A. q/ H! L( U
$ ~  S! c3 y$ i5 }
static struct i2c_driver pcf8563_driver;
! R( `( ], E. i; X3 H
9 c3 o9 z* i0 c9 Z- t& O; m
struct pcf8563 {
. x. b! f) Q9 ]$ C8 ~
        struct rtc_device *rtc;; p  L; w1 q1 O1 v+ w
        /*2 O4 k+ w5 k' y& P% u5 c; a. N
         * The meaning of MO_C bit varies by the chip type.6 Q) @8 N* Z" @. B" H; [4 W, c
         * From PCF8563 datasheet: this bit is toggled when the years
, l, U5 q. T! e  Y, s1 G
         * register oveRFlows from 99 to 00
9 J% f* I' |- c+ |" K8 A0 R
         *   0 indicates the century is 20xx
/ D, [: a2 p# Q4 |8 V. U) o6 K6 q
         *   1 indicates the century is 19xx, R9 s: v( w* c7 g! V, W
         * From RTC8564 datasheet: this bit indicates change of
* \8 Q6 x- h* _( g% p; _# P
         * century. When the year digit data overflows from 99 to 00,; J. Z% M5 r: Y  w+ Y0 H0 m
         * this bit is set. By presetting it to 0 while still in the0 f2 |# G+ B- H; p' M. ^
         * 20th century, it will be set in year 2000, ...3 d$ n8 \% b8 `2 W; p  Z1 R+ Y5 P
         * There seems no reliable way to know how the system use this
" F. j& H4 \) F& I
         * bit.  So let's do it heuristically, assuming we are live in# t0 E& y8 B5 m& U
         * 1970...2069.
7 ?7 {1 V& f% Q+ v1 Q3 F
         */; Y/ z6 P, z8 i
        int c_polarity;        /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */' A: b$ n4 ^( Z* Q5 {
};
! X2 h; M" c! T/ K# ]/ f

: E& R: W0 ^4 k, x4 W" x3 I* c
/*# N2 d: w; R. [0 f0 ^2 p
* In the routines that deal directly with the pcf8563 hardware, we use: h1 G4 i2 [# Z7 U) M2 X: F
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
! g: u1 K3 u, e6 s# ^
*/
1 C9 p2 Q) o2 ~& \0 D
static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
* J- q! U6 I0 r! X9 u1 g
{9 b7 P. {1 u& o# q
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);3 o" p& N0 N  H
        unsigned char buf[13] = { PCF8563_REG_ST1 };
+ ?! D* V8 q$ h

( g  x4 h0 J% O" [$ _7 K; |
        struct i2c_msg msgs[] = {6 K% t" t4 f% P0 }% W
                { client->addr, 0, 1, buf },        /* setup read ptr */
' S1 J" j0 W# F
                { client->addr, I2C_M_RD, 13, buf },        /* read status + date */% k+ y3 ]/ I+ _& D6 t7 y# _) Y
        };
  T$ b# }9 H6 d( H6 l1 h9 A/ `
8 J9 g; X& b. P8 S/ {: O
        /* read registers */, B# O) F/ U" z% ^8 d/ `
        if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
6 v; Y2 M# C. n+ |( D6 M. p5 C
                dev_err(&client->dev, "%s: read error\n", __func__);
: o' w9 S0 g/ {' s5 ]
                return -EIO;
8 o; i# V( P# l: L
        }. L6 n* A* z) a. [
  U5 \3 v5 }$ C- G# K
        if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)2 L: k5 M6 O8 Y* a- a
                dev_info(&client->dev,* W0 L! B9 ~3 j( Q+ M7 b7 ]
                        "low voltage detected, date/time is not reliable.\n");
3 l7 y/ j; s) p' [9 Q
3 Q6 ]- r9 J+ e
        dev_dbg(&client->dev,
8 Z3 |, l& b8 C# P
                "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "; C4 q/ v* t( D: b5 N; |& [
                "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
# K- E( `! H0 o6 |% Y, y, j8 ?
                __func__,/ V/ [; a% S2 H0 Z" d2 l3 K
                buf[0], buf[1], buf[2], buf[3],
# r0 B/ Z$ U1 q5 u, I
                buf[4], buf[5], buf[6], buf[7],7 @: d* f/ E; r, B" \' a
                buf[8]);
2 P# s1 V' K( X1 T5 P
0 s/ P1 e3 i9 ]( Q( ?2 ^

$ q( O" H. D% L8 C; R
        tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
$ p1 H- A! e1 t
        tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
) }, y' k. r, y* V" M/ W
        tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */3 n% ]9 {; M, v% X5 F& x1 g
        tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);  p3 Y$ y8 L9 p+ C+ s
        tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;, H5 a- W4 k7 R6 W4 {
        tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */& T8 Z$ n: m5 ~9 E4 [
        tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
9 p3 l) j3 b5 u' t
        if (tm->tm_year < 70)% ]( [2 C& z' j2 h1 v6 {* R
                tm->tm_year += 100;        /* assume we are in 1970...2069 */
0 q2 n2 J3 b, @/ }
        /* detect the polarity heuristically. see note above. */6 r/ S& r9 s0 y2 F
        pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?4 [2 p: E' U2 a7 ^" k- A9 \
                (tm->tm_year >= 100) : (tm->tm_year < 100);
7 \- W" G8 g1 K1 w( f

9 J% }3 F+ t0 a1 a0 w) G/ C
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, ") ^. N; G" B1 T
                "mday=%d, mon=%d, year=%d, wday=%d\n",, u! O  S$ U( o1 I4 D6 l3 f9 J) F
                __func__,
! \  _3 w! W' {- r- R. p
                tm->tm_sec, tm->tm_min, tm->tm_hour,8 T% k- P, I* C) y
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
' W; T) _5 h& z: F8 r3 S

+ }+ F( e4 P- @! h! v
        /* the clock can give out invalid datetime, but we cannot return
' v: l' h" x& }& G9 o" Q" O
         * -EINVAL otherwise hwclock will refuse to set the time on bootup.( A1 [' I# v% Y( d1 K' A+ ?+ a
         */
+ t' Q' ^" C1 E& A6 f; b+ E
        if (rtc_valid_tm(tm) < 0)" s1 {) J+ l1 q+ J. o( L2 O
                dev_err(&client->dev, "retrieved date/time is not valid.\n");
& h& M- B7 V  ~  y

; C9 R7 P+ M& W* L4 T) j
        return 0;
; |1 x" H5 Z3 O' F" o
}4 M& E% E2 T+ o, H0 Q% C# r1 ~
3 \/ x4 B$ Z8 Q. d  j: R- @
static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)/ D' m8 C' M+ v
{# @. a8 Y- {( [' t. Z( t3 K
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
! B: ~5 }5 ~" E4 |% k" S, Q/ c
        int i, err;
$ i+ p! K; a' E2 Y$ C; e* U+ d1 Q
        unsigned char buf[9];
: N2 D% |, A5 U' _! p( j) d
& D2 G  }( @/ U- M8 `( ~0 X# ^4 h. F) y
        dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "# n0 q# f% G  I  `* J) @6 w
                "mday=%d, mon=%d, year=%d, wday=%d\n",. L. |5 A9 d3 R2 u9 ~
                __func__,
6 y7 O9 z1 a# o) r( `
                tm->tm_sec, tm->tm_min, tm->tm_hour,
* L/ I! }$ y! _, o+ U: H+ ~- e' ]0 S
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
! K" }& `; n; T' E, G: P

2 M1 H" F5 y1 n. `0 s% z
        /* hours, minutes and seconds */
' L- o# E. Q+ p. A
        buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);: x& k8 J" q2 Y. V/ z  P
        buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);3 j8 I" f- |- t& K& f7 P; ?- z
        buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);0 r8 ]/ g! G. [6 G2 y' q3 J  `# D3 h
% }' ?# A: {4 e
        buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
( R9 ~8 X2 Q  V" x

" U' \  _6 @5 [5 O! t/ h
        /* month, 1 - 12 */
* p9 X6 l% d2 N0 k2 h
        buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);3 Y- F& i/ Q/ x8 \7 v, D/ ]

! a; m7 J' T0 k: o% e" Y+ ^
        /* year and century */
9 M/ O' Y) |6 }% d' `9 ^
        buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);6 Z& n) d* w% W
        if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
4 Y1 ^: ~; c& n' x; ^. w
                buf[PCF8563_REG_MO] |= PCF8563_MO_C;
; S, N6 w% O% Z! g0 `2 O3 t
  k' d8 T, x! H9 e) e; R
        buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
2 K9 h  S0 h' S- @
" n; ~' v6 n8 W& c6 O& D
        /* write register's data */! j" k, a. X, H* M; D7 ~% k6 M
        for (i = 0; i < 7; i++) {! S- x$ {. Z8 ^% E# }
                unsigned char data[2] = { PCF8563_REG_SC + i,9 f. b- M2 V  J! ]& Q( J
                                                buf[PCF8563_REG_SC + i] };
* e; L( m7 l( i3 n* P; [( b. e- O

4 u& ]+ C4 w: w& o  Y$ j# \
                err = i2c_master_send(client, data, sizeof(data));
) ?9 P8 f4 Y; H6 t& j
                if (err != sizeof(data)) {6 q# v! P4 |3 J% H2 n9 |# w
                        dev_err(&client->dev,
( `3 j& B, U  g3 z6 A0 K2 y$ x" C
                                "%s: err=%d addr=%02x, data=%02x\n",
- _; R4 e/ v6 L
                                __func__, err, data[0], data[1]);
( g! E! z8 D0 r& t# G/ }
                        return -EIO;
- n) ]8 V3 X6 b
                }& ]. k# \+ a- N8 z( h4 f
        };
- a+ @7 w8 A2 j
( k1 ^' r4 Z; P" X  J3 w" t9 ^
        return 0;5 I/ Z! g4 |) {) y& J6 n
}
+ {; I3 G/ y9 t! [% m8 Y6 p& k
" R! l8 F% G+ Y6 m1 m1 L* Y& ^0 q* G
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)! `2 e# h& D7 v' k; I
{
& i8 ]$ m' E% \0 M
        return pcf8563_get_datetime(to_i2c_client(dev), tm);4 t& R# |7 h8 G( I
}; Z" c0 C$ h8 X* v3 u5 o3 k
0 R* u* S1 }( [- U
static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
8 q  c4 t/ a) m9 N/ y
{
, T9 r% z/ O% I) X5 E8 K% D
        return pcf8563_set_datetime(to_i2c_client(dev), tm);/ a7 K2 {% f% ^
}( i4 N$ W: o! r
4 P) @1 f7 q8 i2 {5 ?" J; n: i
static const struct rtc_class_ops pcf8563_rtc_ops = {
( N  U2 N. @; n+ V8 W) F
        .read_time        = pcf8563_rtc_read_time,
7 {3 g! d9 r$ c' x
        .set_time        = pcf8563_rtc_set_time,
% E2 j* }; S# e' D, I/ W
};
( O- k9 v2 K6 J6 z( A# d, b
! V" }$ e( @' ~3 M% ?
static int pcf8563_probe(struct i2c_client *client,
( u3 A" ^; B% w2 X7 w& ^
                                const struct i2c_device_id *id)
) h3 J! j1 q, e9 T: J
{
  m* n! `+ A: O$ b& ?
        struct pcf8563 *pcf8563;1 k, b! N# {5 ~  A  B( w) Z1 |
* w' v9 y  S7 U0 A& r% S( f0 o' s8 x
        int err = 0;0 u0 n) Z' c1 f1 R5 X

' r+ I5 \- B1 o0 n+ w# y! x1 B' ]; [
        dev_dbg(&client->dev, "%s\n", __func__);
$ C! e+ @% v5 f* m# j& R

6 g/ }  h+ P8 B7 {" f& p
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))1 Y- m4 w& C# n  k6 n5 x* t
                return -ENODEV;2 ]$ L3 R) x8 X( M  z0 K

( O6 T# F) F$ @: B% s( h  \
        pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL);  {. \9 z: ?; m9 ~! `- v: u
        if (!pcf8563)# J) a$ h2 L% @; `" ~! B1 O
                return -ENOMEM;+ a4 v, P5 n* v' I5 I( \5 h3 K
! P% \9 ?( h. Y1 o4 Z8 b
        dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");  E& l' J& D6 k) x1 O
5 n9 c: f- s: F  \: p0 C
        i2c_set_clientdata(client, pcf8563);* R) Z0 Y! M  T1 e
0 ]2 d: Y0 Z# P  j6 j* H
        pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,, k/ g4 x* |0 w* S% d* G1 K
                                &client->dev, &pcf8563_rtc_ops, THIS_MODULE);
! z1 J( q' B8 `( N! i5 Y
, z* U) G& I6 C5 ?) ~( N
        if (IS_ERR(pcf8563->rtc)) {4 P- z: O. Q" c  Z2 F
                err = PTR_ERR(pcf8563->rtc);
9 }! }" s) h& Y4 \9 P  }( v
                goto exit_kfree;6 B  V0 n# |! v( E) v
        }2 }8 F# Z' |6 x

. a; t# }4 b/ k, {
        return 0;
& Z: A4 ?0 d# u; w; ^/ X9 V
7 ]6 B1 a( x: {/ O
exit_kfree:# y3 P9 O; h5 i8 u$ Y& d; V
        kfree(pcf8563);: J4 {0 x2 D4 e1 d  F5 e! d

5 z; P2 o, P7 ~3 D1 k- O# K
        return err;7 B# F" |; b" M* J+ O& ?7 S
}6 ~4 w( `' P$ H
8 U2 v) b. `$ Y! ?! h
static int pcf8563_remove(struct i2c_client *client)  d5 U. E1 C! ^2 ^: _
{
8 k. V0 b2 M8 P
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
# F8 _0 p+ b' w6 v' C9 t
  l) t! V3 A& w" a0 K$ ~8 m
        if (pcf8563->rtc)' q4 ]: U. g5 o6 Y# h0 f
                rtc_device_unregister(pcf8563->rtc);
5 K9 ?" q) p9 \! P3 i. B! H9 N
5 j' K& S* e# m5 L5 [$ |4 T
        kfree(pcf8563);
1 X/ V1 K& L1 I0 A3 H

* i* m9 n4 J1 ], w2 {+ R; L2 l
        return 0;- }3 ]+ }" C, y" F/ o1 _
}
! g% J7 B/ A7 ~9 T% C, ^( L: ?
( h( C/ M% q1 V. T; f0 I5 x9 V1 H
static const struct i2c_device_id pcf8563_id[] = {' ^9 r* S2 T/ T' D2 }; l5 |
        { "pcf8563", 0 },/ e' W; L  T: M; I* A* e
        { "rtc8564", 0 },8 A' t( I6 v/ P' X8 H. v
        { }
* I. j& |  c1 U) Y4 |0 g- \: }
};% {2 F1 M9 T$ B# U
MODULE_DEVICE_TABLE(i2c, pcf8563_id);
- c8 a$ p; A7 h- a; R0 o( D

( }* I" t, |8 p1 w! g
static struct i2c_driver pcf8563_driver = {: t1 H9 V, d. \/ M
        .driver                = {5 V- n- S. ^5 V" _- q- r
                .name        = "rtc-pcf8563",( l1 |. h- `& B8 h( v; s) D6 B3 h
        },
3 b& r% u' M7 K
        .probe                = pcf8563_probe,
0 f# {9 D- F' F, X
        .remove                = pcf8563_remove,; a2 L  H7 C. K6 K1 M
        .id_table        = pcf8563_id,
$ R& i7 a! s: \, Y
};$ P( Z& O/ X  W

. {7 Z5 f, E) _9 r$ e4 r& k
static int __init pcf8563_init(void)
5 T1 x9 Q7 L# B1 J5 r  ?* L
{
( i) ^/ C  ~$ ]8 V0 ~( s! Y
        return i2c_add_driver(&pcf8563_driver);
6 R2 \& {" ~: N  w" K3 l
}# y9 V+ ]6 T1 |
& }  z, ]; a2 n% D/ J: Y( X
static void __exit pcf8563_exit(void)
1 B$ s8 C0 h4 t" g9 l: e. R! B, ?4 i
{; v5 I! j! O7 T) A  Z+ s7 A
        i2c_del_driver(&pcf8563_driver);
2 e6 A1 N/ [9 O8 b" R
}
5 x: j1 y" J$ i: N, y) h7 t
: ~. W: p3 S/ w- M1 b. q
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");! a1 [# R. v; S+ _6 J9 p% ]
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");7 g( u# M) V! X% }
MODULE_LICENSE("GPL");  v3 Z2 l6 I/ d( B9 W9 o
MODULE_VERSION(DRV_VERSION);# C6 P) I5 k7 Q3 K/ D; c

# r+ i+ q; u6 m$ ?; B, u8 [! p: p
module_init(pcf8563_init);
5 c, l5 y6 T7 p. T
module_exit(pcf8563_exit);

9 U7 e3 O8 _2 J5 O

该用户从未签到

2#
发表于 2017-11-24 10:47 | 只看该作者
这么一堆,看蒙了,不过还是了解一下下

该用户从未签到

3#
发表于 2017-11-25 20:27 | 只看该作者
哪个正常的人能崇拜一只蟑螂呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-11-24 13:03 , Processed in 0.203125 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表