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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
: ^; X* ~0 {$ Q2 i0 R# Y2 J' q$ J2 O- P
开发板:
各位版主、工程师们你们好:
      请教你们一些问题:
             1)在内核中配置pcf8563时钟芯片启动完成,内核启动后 /dev/rtc/ 中没有pcf8563芯片对应的 rtc 节点;
             2)内核启动过程中打印 drivers/rtc/hctosys.c: unable to open rtc device (rtc0);
             3)pcf8563芯片驱动程序的 pcf8563_probe()在整个启动过程中没有被执行;
             4)请问这是怎么回事?该怎么修改???
             5)驱动程序代码如下:
驱动代码:
0 k* z8 T9 l6 I3 i& R8 s' B
#include <linux/i2c.h>
9 Z: {+ O8 ^" t( g
#include <linux/bcd.h>
( ]# t  a! C/ S+ y! ^
#include <linux/rtc.h>' k2 b1 \& l  ^; s+ t
#include <linux/slab.h>- R" I2 y1 f) ~1 J9 |

* X, J& d1 @! d  e! m6 X: W
#define DRV_VERSION "0.4.3"
. y, ^- U" `: D' D, ^( n

5 K: n7 V4 f# N  H. g- A
#define PCF8563_REG_ST1                0x00 /* status */
. X5 [4 r2 d& G+ o
#define PCF8563_REG_ST2                0x01# F% @. L0 h" q
, |, T$ F1 K* i0 X* E$ ^
#define PCF8563_REG_SC                0x02 /* datetime */2 ^) n+ d4 y* W- g
#define PCF8563_REG_MN                0x03
6 X: i! h  s! J: h: B: O2 C
#define PCF8563_REG_HR                0x042 D& R/ q9 a( T& k7 o( {
#define PCF8563_REG_DM                0x05
4 ^( M; _9 v' ^3 M. w( O
#define PCF8563_REG_DW                0x06& e6 a7 z. ?' w. v# L
#define PCF8563_REG_MO                0x07
) `6 N6 s, n, m0 h* O! D: J
#define PCF8563_REG_YR                0x08! T& s# }7 d# L+ F! ?: O
3 X( R' R, ^; E; t
#define PCF8563_REG_AMN                0x09 /* alARM */  J5 s; E0 U7 @( U4 |
#define PCF8563_REG_AHR                0x0A
: d4 L8 D3 i5 t
#define PCF8563_REG_ADM                0x0B8 e7 L/ O8 Z# o( B
#define PCF8563_REG_ADW                0x0C+ k/ u% T; D/ M) T3 ^
9 w* k# B& V) Z4 x7 J
#define PCF8563_REG_CLKO        0x0D /* clock out */  y( I! \4 r6 M( Y: ]. S  s# p
#define PCF8563_REG_TMRC        0x0E /* timer control */
4 O* r2 Q, x( k3 ^
#define PCF8563_REG_TMR                0x0F /* timer */
( A4 Q) b7 X2 ^' [# e
9 R7 l+ \% m( O( _$ R: g
#define PCF8563_SC_LV                0x80 /* low voltage */* X. ~& [3 u+ V5 f
#define PCF8563_MO_C                0x80 /* century */
5 t7 q4 u6 r3 T2 I
  P3 x: o# u/ j2 J& R% M- \
static struct i2c_driver pcf8563_driver;
3 v+ s  _; n4 r  U
$ y/ V, T6 j; ^, E) e
struct pcf8563 {5 E* D) a: q$ N) F" N
        struct rtc_device *rtc;
4 A3 P9 C) K9 I# h. C% o& m
        /*
( S& L% s4 G& F* V* l0 c; u' u$ V
         * The meaning of MO_C bit varies by the chip type.
9 C3 K8 ~1 R& F1 ~# a: y1 s
         * From PCF8563 datasheet: this bit is toggled when the years
$ v8 y- a6 g' u$ A
         * register oveRFlows from 99 to 00
% S1 @" @0 ?+ W. _, x( l
         *   0 indicates the century is 20xx9 I3 r2 w% l& c" e3 x4 X! a
         *   1 indicates the century is 19xx' q* z+ {) n& |. B+ V
         * From RTC8564 datasheet: this bit indicates change of
. [: }' b& J1 O8 t4 z, c
         * century. When the year digit data overflows from 99 to 00,
* s+ p0 P* M8 Z# P
         * this bit is set. By presetting it to 0 while still in the% _+ k, s. z% ~  `5 Z! O
         * 20th century, it will be set in year 2000, ...
8 x+ ]6 R8 L$ O# N
         * There seems no reliable way to know how the system use this2 F- C0 a2 @; M8 P" d2 ?" q0 w5 M
         * bit.  So let's do it heuristically, assuming we are live in% l0 J6 S! {( J
         * 1970...2069.
/ p. M- v8 z6 [4 u
         *// i( D2 J' @$ Z$ O$ t0 J( u8 f
        int c_polarity;        /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */5 m$ G" D2 u* E  v7 b* ?+ x
};, z* }. k! U" E* y7 u

9 D- y, G4 r$ B6 ?
/** p( l3 k2 ~% ?( F
* In the routines that deal directly with the pcf8563 hardware, we use: g* R! E7 O. A6 ?' L/ M2 k
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.4 b# {  P: U) k1 Z
*/6 f' _3 H5 R# W% X7 k
static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
4 a( a& r& ~( _* o+ ^8 n: U
{
6 @, n' T" }, p, p$ F6 V
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);  y/ w. ~4 R5 q; `
        unsigned char buf[13] = { PCF8563_REG_ST1 };% m* p3 j; P4 ^$ D

2 M$ A8 l, O& b4 _2 X/ I
        struct i2c_msg msgs[] = {
( y0 O4 X) w0 f3 v+ L+ ]4 b' Y2 s
                { client->addr, 0, 1, buf },        /* setup read ptr */$ q8 F* S0 B( s- {$ ?; Z! w
                { client->addr, I2C_M_RD, 13, buf },        /* read status + date */0 M& g6 ^. s- k' `
        };
5 J7 M# y- }8 j3 d" t
5 d# ?# M0 \( C  }
        /* read registers */
4 @- ?* S3 `1 n+ l4 ~
        if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {4 I5 y" u4 ?2 |7 c5 X" }! c$ O
                dev_err(&client->dev, "%s: read error\n", __func__);
8 [+ n7 o, j7 o" n
                return -EIO;
1 _6 Z* |8 ]# J% t: U% b5 H( Y
        }
5 [9 w$ f" A0 f1 T
' J& E& n% K5 X1 Y: V7 h
        if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)
. x3 b0 u( S7 m* K
                dev_info(&client->dev,1 R+ `$ k) [0 n2 }4 Q; o" m
                        "low voltage detected, date/time is not reliable.\n");( E, t% ?  B8 A8 |& T
2 y0 S5 z- E, x7 N- m* x0 v
        dev_dbg(&client->dev,
8 }+ d% y* I5 v
                "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "; f  ^1 Q$ ~2 {% C1 K
                "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
! }1 c9 F- b- O
                __func__,
* w. Y3 `6 t- x9 R; H/ Y6 z& u
                buf[0], buf[1], buf[2], buf[3],' l7 C5 r2 _9 O) x$ b  P+ U
                buf[4], buf[5], buf[6], buf[7],
9 u3 f* l3 ?+ J0 m
                buf[8]);8 q( g' ?; L6 P6 A5 k

7 c7 r8 E, f6 l3 d! [+ i) {

+ u' ~7 ]8 W9 c* S1 s
        tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);% g7 i- W: O# [. m: s- a
        tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
& ?8 D' Q5 ~4 \  d& Y6 }2 }4 r1 L% P1 `0 @
        tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */# z8 r& r- P& f) s$ O1 _, T
        tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
; k1 i) r1 q: O" H# k
        tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;3 o+ h; X8 `7 \/ x9 ]$ a
        tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
" U5 Z8 H; U) L6 R5 o( l, P
        tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
$ i# J) X1 [# @' n5 m: ~" n8 V
        if (tm->tm_year < 70). M8 R% K* I3 S3 K( h$ n2 n
                tm->tm_year += 100;        /* assume we are in 1970...2069 */
$ p/ G, r+ }: x2 F. K
        /* detect the polarity heuristically. see note above. */
' W3 I8 K) _" f' n; n/ A
        pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?& q# i0 P6 r4 Q% B
                (tm->tm_year >= 100) : (tm->tm_year < 100);; v9 c% h# T9 f/ H

' i+ x% U5 x" ?
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, ", k$ w* W) C# l
                "mday=%d, mon=%d, year=%d, wday=%d\n",
5 F1 g' J7 K, P. @
                __func__,
  v  P- |* P" ~
                tm->tm_sec, tm->tm_min, tm->tm_hour,
; n+ H, \# U. q
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
$ a4 B0 Y1 h0 Q: N

3 X7 k+ ?6 y! a
        /* the clock can give out invalid datetime, but we cannot return5 ^- Q# c3 ~: F- c; T, Y
         * -EINVAL otherwise hwclock will refuse to set the time on bootup.# B' g8 S9 F- R) m
         */
8 A2 _" b; x% P( P4 C  y
        if (rtc_valid_tm(tm) < 0)
5 H0 T2 X" D$ m# d4 g+ Q2 ]9 f
                dev_err(&client->dev, "retrieved date/time is not valid.\n");" O$ o2 H/ g; Y

, S0 S* O+ A9 C* o0 h. O, \
        return 0;
! j) f1 F# K7 l4 g% O
}
* s; I& i% N, R2 L; m

) q2 [/ ?2 ~9 F" w: V' b
static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
7 ~- w5 o/ P% `
{3 C, X9 s, g) }8 b$ ~, q4 F1 L  Z) R
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);' x& ^, |! R$ \0 ?6 s0 ^, j% H
        int i, err;
1 `! S& q8 E  z( m: B
        unsigned char buf[9];
( {/ S8 f0 k' y8 E
/ t% e6 ?( R' [% @3 `! V
        dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
) g) `, c% F' ?6 i% Q& E/ i: B
                "mday=%d, mon=%d, year=%d, wday=%d\n",( f; e: `4 a+ J' H4 [) e1 w7 [
                __func__,
! \/ n! s8 q) H; R4 ^, t$ d
                tm->tm_sec, tm->tm_min, tm->tm_hour,% M( J2 ]- R/ ^* H3 N
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);; d* t. b* Q: D- ^0 M$ J
1 N8 L# z; [9 t8 C- s' V* b1 T
        /* hours, minutes and seconds */
" f5 z* {4 Q1 h8 K3 r
        buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);
5 `. n! g  G% u& h
        buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
/ B- G) {: f  X5 A9 l1 r
        buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);2 Y# s1 U4 R. ~- r& O3 v0 l

8 \+ O. O4 }' o* Y
        buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
0 F* E( d" m# x5 @" b# a
* s) e! [1 c$ O" E
        /* month, 1 - 12 */
) `) I& y0 m- `1 [7 }
        buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);, l+ W; Y. B' p4 L4 M4 u) F
/ ?0 U0 K/ J" B7 M- ~2 y
        /* year and century */
; V( M4 X9 G( E! y
        buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
4 O! N6 J7 n0 z
        if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))' Y, G; z4 ]/ l* p% _  ~) D) h- b
                buf[PCF8563_REG_MO] |= PCF8563_MO_C;
& K# J% S2 A! m! x, `) H8 D1 h& a

6 t6 _) [1 r/ Z2 C4 C' A
        buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;) Y: O" i7 @/ o4 _9 Y7 @3 {

' a. {2 I; _3 l0 x8 O2 y
        /* write register's data */* y4 p- F, O5 G2 V1 `
        for (i = 0; i < 7; i++) {
$ @/ d4 a; E5 }/ W4 n2 y- V+ h* e
                unsigned char data[2] = { PCF8563_REG_SC + i,0 S- E+ j( T$ I* w
                                                buf[PCF8563_REG_SC + i] };/ F! }: r) i+ S8 k  W( x" f

/ W7 R+ s3 J; z" H8 E) ^# O
                err = i2c_master_send(client, data, sizeof(data));
) R- c! h: F7 \) S* H3 B- s3 g
                if (err != sizeof(data)) {
% u1 k* X, ?' l7 [/ q* \
                        dev_err(&client->dev,
0 i" w$ o- R8 z" F1 O
                                "%s: err=%d addr=%02x, data=%02x\n",
7 i+ i9 g6 r7 K1 k7 J3 s
                                __func__, err, data[0], data[1]);/ `0 h* a& Q* ^
                        return -EIO;
) c4 ~- P% J6 I$ s" }. r) |
                }' c2 \+ j% _) I1 F" h1 W5 j  K4 P6 }
        };
, r7 z- D2 n8 d% R  Z% l# L, n
2 j0 u' R* p5 w* l1 a$ `/ g/ p
        return 0;
; B# z" H2 I7 q# p; }
}4 n$ W# o; x9 `% n" t9 ?( o
: ^4 |7 h! m" Y
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)) W0 |' P0 @7 t' g  B1 ], ~' e
{
. a+ J6 ~( r9 Z" n# I) @7 R
        return pcf8563_get_datetime(to_i2c_client(dev), tm);# i( K& c2 a: w
}& J2 ?8 t* q# l

4 r( w% ^) H  b3 K+ o
static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm), L; B& M- M2 P8 e1 ^
{+ p# x: l/ S8 U: F5 h
        return pcf8563_set_datetime(to_i2c_client(dev), tm);
  L$ y1 Q. ~$ w/ V3 W6 ^3 a% X9 v
}6 l& H1 r/ \" P* w+ Q+ A% i3 r
$ t4 C3 l; Z- X! Q) Z
static const struct rtc_class_ops pcf8563_rtc_ops = {
3 Z* }* ]% c3 T, Q1 a
        .read_time        = pcf8563_rtc_read_time,
% ~6 o* x2 v, I1 W9 x) V5 G6 m3 Q% l9 u
        .set_time        = pcf8563_rtc_set_time,
8 P! d" P0 y" r. n; O3 Q
};4 a* q9 Q! V- z3 L$ \
9 f7 v# b4 f7 i( _
static int pcf8563_probe(struct i2c_client *client,
$ s7 j+ ?& Q  c1 f% X
                                const struct i2c_device_id *id)" A  c4 Y2 ~- m6 U  o& M' f
{3 z( r: U7 W! ~
        struct pcf8563 *pcf8563;
3 q' k) k9 e; d
( ]' b4 A4 V& z% i, `( c& g* I2 @
        int err = 0;: b' t9 X* b. q
+ n0 Y/ S2 c+ j
        dev_dbg(&client->dev, "%s\n", __func__);
, P% s, Q  s7 y3 n( l6 H' _  h

. B# C; d6 I* a: Q
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
% ^5 O' b; L: ^6 N- @
                return -ENODEV;$ v; x7 c7 ^. ^, W
. v7 H: C7 d: L# a, i: `# H
        pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL);
3 J. N% Q  m; l
        if (!pcf8563)
. a8 q* _3 W# U0 |, t9 b  U
                return -ENOMEM;8 x. K. o) \7 W: l6 h

: m9 e) S6 e, q* S, S: p
        dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");% m3 U2 ^; w3 `

! g9 C9 x1 w* f7 ~$ [& ~+ `
        i2c_set_clientdata(client, pcf8563);
! h; v: G+ u7 r. I) y) M* g' R

0 I0 S/ a2 v* M( _' S
        pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
% o$ v( Q8 S! M6 x( a8 x
                                &client->dev, &pcf8563_rtc_ops, THIS_MODULE);# V. j' l) D* N# j! K
6 h- J% r5 @) O3 [3 C
        if (IS_ERR(pcf8563->rtc)) {
' X. G3 d7 k. U! @) n. F6 e/ y
                err = PTR_ERR(pcf8563->rtc);, G, R: l% |4 l8 ?, G: ?
                goto exit_kfree;
# p2 V. w# A+ K6 M. T1 {+ ?  L
        }) C. j6 J* j4 C: E
7 c8 y4 R" v  G2 n4 j# a
        return 0;% a1 D7 S( R, [- L" E* v% M$ j9 C
+ `; E2 }% X9 W7 o1 x# d& @) e2 n
exit_kfree:/ z& R7 ~! }7 A# d6 T0 Z- B
        kfree(pcf8563);5 n  b* R4 F' |" b6 `5 H% |% N

5 I8 p/ P& Z6 `, k: [1 Z1 x9 T* L
        return err;  C8 W, c. _$ V! z7 V3 T7 m! D
}
! H  |" T( C. T  `
) ]: Q5 I" p7 A- s
static int pcf8563_remove(struct i2c_client *client): B; Q: \7 W2 l* r5 i- x
{( ^9 w7 ]( Y; @  }3 f
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
. k6 y2 _% H+ o2 c: m- w  D
7 s. B/ Y, v, L! _/ W( S# K
        if (pcf8563->rtc)
( ^) D3 b+ k! ~1 v
                rtc_device_unregister(pcf8563->rtc);/ I1 d% t4 N! G8 z

# B7 G+ i% Y1 ]* ~0 ]- [
        kfree(pcf8563);
: |2 h1 S; u6 g* a/ ~. N( n  S" v; I6 M

9 y9 ~9 `# V' B" j, ?
        return 0;$ B7 L) [6 t$ A# |8 R3 K8 C
}0 q) P* b# x! u5 l- O
- S" K0 ~  P& G% ]* _$ E
static const struct i2c_device_id pcf8563_id[] = {
- c! A; r5 m! |/ V2 P9 C: n4 Y
        { "pcf8563", 0 },/ z/ W* U6 s) T( g7 j
        { "rtc8564", 0 },/ A+ i4 s& a& j- V3 Z
        { }* S3 C) B% k5 ^, t2 N6 i3 t
};
6 Q- z- w& l& u. S
MODULE_DEVICE_TABLE(i2c, pcf8563_id);$ e8 `' s5 G8 d% l& G" T. `
/ A, q4 S; v( c; k  C5 h- c
static struct i2c_driver pcf8563_driver = {
! e: s+ n# R7 \2 ]( S
        .driver                = {
  `# Z% S. E: W
                .name        = "rtc-pcf8563",( o+ I! e. Y+ ]: ^  H- A5 t2 s
        },
: X  p3 f+ @' t
        .probe                = pcf8563_probe," S! k8 f+ x/ ]1 P
        .remove                = pcf8563_remove,; b, d9 [5 B% p( ^, e
        .id_table        = pcf8563_id,! R% v/ T) t: o
};& S, M4 h( L8 u% i: m8 x3 n
2 Z5 b4 s2 w* x6 H" K1 Z
static int __init pcf8563_init(void)
0 k7 P/ J! T& D
{
# E: {) f; N5 O6 v; U8 i* T4 e
        return i2c_add_driver(&pcf8563_driver);
9 P3 V3 {! @) J1 j* T$ |
}
' N  Z. y1 a6 w4 H
9 n! E0 V# \6 l6 m( J* M9 q  I
static void __exit pcf8563_exit(void)
6 g- q: B( i, }# {0 ~
{
. C. k/ s! ~1 D6 E0 C
        i2c_del_driver(&pcf8563_driver);
' z! u7 R+ S& I5 D
}5 v( I- H4 e& Q8 S4 c( S, W, ]

1 `( H7 h- ?5 B
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");! o! q" S4 Z, @/ R! ]# f  b
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
* a! M4 y" V3 ?" C/ r" |+ m
MODULE_LICENSE("GPL");9 l4 w& e7 q* D% M# ?
MODULE_VERSION(DRV_VERSION);
7 X2 I2 A$ e& Y9 o+ O0 O9 S1 l$ d

5 p% `. e5 I- N
module_init(pcf8563_init);
0 I- x; \0 l1 c! ^
module_exit(pcf8563_exit);
. B- i: v. O$ E- {+ R5 r: w

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

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

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

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

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