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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x

4 r) l- m3 C/ y( I: N
开发板:
各位版主、工程师们你们好:
      请教你们一些问题:
             1)在内核中配置pcf8563时钟芯片启动完成,内核启动后 /dev/rtc/ 中没有pcf8563芯片对应的 rtc 节点;
             2)内核启动过程中打印 drivers/rtc/hctosys.c: unable to open rtc device (rtc0);
             3)pcf8563芯片驱动程序的 pcf8563_probe()在整个启动过程中没有被执行;
             4)请问这是怎么回事?该怎么修改???
             5)驱动程序代码如下:
驱动代码:
2 V# ^1 L; x. X  E8 e2 B
#include <linux/i2c.h>1 Y7 e. V! K. h. `+ f2 a, @
#include <linux/bcd.h>
" \$ t+ b) P% ?" K6 u. Y7 T2 o
#include <linux/rtc.h># J7 p4 O7 j: u7 L
#include <linux/slab.h>
) O2 P& Z) w' o' ~+ L

8 V6 a* k2 r- u1 |2 X4 h
#define DRV_VERSION "0.4.3"9 d' U% L5 x: B3 S% j

$ u1 I" J: R# a, m7 l  \$ }
#define PCF8563_REG_ST1                0x00 /* status */
/ X$ O$ H, g1 _
#define PCF8563_REG_ST2                0x01& D' X, e( x. l
0 }4 e; k2 v# Z# P9 N$ C4 m
#define PCF8563_REG_SC                0x02 /* datetime */% W6 Y9 L6 [8 {
#define PCF8563_REG_MN                0x03/ }3 p6 c* h# d, O
#define PCF8563_REG_HR                0x04
) l9 l$ K: h2 S' O3 |
#define PCF8563_REG_DM                0x05- f% A' u9 [: {9 x( S1 y8 Y. D
#define PCF8563_REG_DW                0x06
; ~1 r# m2 B+ J6 W
#define PCF8563_REG_MO                0x07
$ ]3 S4 J/ p6 L0 V! p" o+ s$ {. A
#define PCF8563_REG_YR                0x08
9 a/ N6 E/ B( c1 G4 f7 l4 b5 X

! f9 ~$ J; ]' u" Y" Z
#define PCF8563_REG_AMN                0x09 /* alARM */3 ?1 D) l( w: d! y7 e; s* }( z
#define PCF8563_REG_AHR                0x0A
- Y- }0 x9 E( O2 q/ o! n2 d; e0 o: A
#define PCF8563_REG_ADM                0x0B
& O6 W0 r* q( J& V/ W
#define PCF8563_REG_ADW                0x0C
' _  p9 C& x2 Y: V* x

* r# x) F7 T& E+ a/ y
#define PCF8563_REG_CLKO        0x0D /* clock out */( D2 S( {' V& w% R8 Z7 R
#define PCF8563_REG_TMRC        0x0E /* timer control */
, N. d' W3 @% d8 n  H0 x
#define PCF8563_REG_TMR                0x0F /* timer */
5 o' M& l& b3 K# D! b/ \1 z
8 F3 v8 k9 f! |* ?1 ~3 s
#define PCF8563_SC_LV                0x80 /* low voltage */6 a/ L' D# U8 F! Z* c& C
#define PCF8563_MO_C                0x80 /* century */3 i0 c) t0 u6 W/ j8 G# a
7 W9 ?7 c7 n# m
static struct i2c_driver pcf8563_driver;1 T+ I. o1 Z1 O2 K7 _& O

- k. Z% I8 P3 M$ d8 z
struct pcf8563 {  d9 K* z2 p1 C. c- U
        struct rtc_device *rtc;
; |7 p1 B6 a% U- o$ L, e- d( k
        /*( H- h" Y( B5 X. {
         * The meaning of MO_C bit varies by the chip type.' ~2 i8 v6 v0 ~/ y" g
         * From PCF8563 datasheet: this bit is toggled when the years
; h' e" U( x9 d! c4 O9 h  G' ~
         * register oveRFlows from 99 to 00
7 v6 L) u' b8 ^' u3 c: R) V
         *   0 indicates the century is 20xx0 M9 _7 J" M: C
         *   1 indicates the century is 19xx& @- P$ F7 k' ^
         * From RTC8564 datasheet: this bit indicates change of
! m" I' v8 B$ U8 Y# R7 {) s
         * century. When the year digit data overflows from 99 to 00,
/ T+ \  p9 C6 r2 u7 q4 L" k/ t+ K
         * this bit is set. By presetting it to 0 while still in the0 h" {, @$ B- l' q( ^: b/ [# d; @
         * 20th century, it will be set in year 2000, ...% |2 L' T! ?% i" j- m1 u; X' p
         * There seems no reliable way to know how the system use this4 {% N7 e  G) Z" l& K. Z6 P3 ~
         * bit.  So let's do it heuristically, assuming we are live in9 V) b1 m- T( M7 w% h; u" B
         * 1970...2069.7 S2 Y7 n+ Z" |4 i) ^1 X8 r
         */
, y' G. K8 A- j' a1 g) q
        int c_polarity;        /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */+ @2 Y: C0 K* Q& H5 `) e
};
- W7 C) c" O3 e! w) O7 t5 |; ~8 N# K
6 i! M$ T0 x8 ~
/*5 N$ O' G0 d2 h) l' K' _5 J
* In the routines that deal directly with the pcf8563 hardware, we use; a& ]# |% S+ F! L, D
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.0 m+ k  G8 Q- g
*/$ j9 B& p8 Y! r
static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)+ z5 g5 s/ A& r# X: A* d# ]
{6 w! [/ S: _" i+ H3 ~
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);' o% W$ _1 W- K8 b, n1 h! M, u6 d+ n
        unsigned char buf[13] = { PCF8563_REG_ST1 };" a# U( z- U  n  E) A: l- F2 l
% X5 E5 R5 Q8 K, U+ S$ c7 }1 E: {* @
        struct i2c_msg msgs[] = {
9 g* B6 Y0 C% v! S, H) w( M
                { client->addr, 0, 1, buf },        /* setup read ptr */+ P4 U6 A& I: O6 u* Z( [
                { client->addr, I2C_M_RD, 13, buf },        /* read status + date */! z4 q# j& a! X
        };; q6 m$ p$ N; V$ r

  |2 e' N, K3 u/ x3 n' E* E7 O
        /* read registers */
) W" ]# |! u! J$ W8 ?
        if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
$ n0 F8 L- r0 i0 P  a
                dev_err(&client->dev, "%s: read error\n", __func__);
0 [- C* c/ C, S% c8 ]
                return -EIO;
2 I8 d2 k& n: i. [; K/ [! r: i
        }
0 P9 J+ G: P1 ^! o* C$ d

8 p* M7 C) r  |6 P$ n, W
        if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)& Z6 u1 n5 G( K
                dev_info(&client->dev,% ?" q0 S, J# K' M* w, o
                        "low voltage detected, date/time is not reliable.\n");
" \; M3 s0 {4 E+ p! e0 j# e" t

) P2 V( C4 o1 i
        dev_dbg(&client->dev,7 M2 o6 ~8 M8 b) H! ^7 S
                "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "5 M  }3 B# d) Z, E
                "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",& ]- C- K& _/ f8 h- p
                __func__,
" G0 i) J& h4 ^& s% @
                buf[0], buf[1], buf[2], buf[3],
" u) L, k5 Z* ?7 V2 G7 m* W
                buf[4], buf[5], buf[6], buf[7],
5 M2 q: x/ n: m2 |( ~3 k5 [" W
                buf[8]);; D; z& ?4 \( m0 i: K5 M

: H& F' q& @' G! z) B8 u- p

; e. _. A& q. S% ?0 E7 O
        tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);5 \* c0 u9 H, C% _# ~7 h
        tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
. ]9 B5 E6 R2 m$ n7 \5 _6 p
        tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */! X; Z, b2 L9 V- L  \8 h5 @" d
        tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
$ g) O* I6 ~5 |1 A
        tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;0 n8 D& U# R3 w* ^( n1 K( u
        tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */2 o% j/ D5 |4 x9 N9 ~6 u1 Y' T* Y3 i
        tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);4 o& V  f% c+ J5 o
        if (tm->tm_year < 70)' v! e, K" P% i' o3 I
                tm->tm_year += 100;        /* assume we are in 1970...2069 */2 d  d0 K, ]6 ^& q! Y9 ]
        /* detect the polarity heuristically. see note above. */1 \  ~0 H# }) c6 D
        pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
, V/ z' L# l2 U: }/ H' V7 \4 l
                (tm->tm_year >= 100) : (tm->tm_year < 100);
+ W( e; l  R, v, U! \
# U- f2 N  q3 g  J  h
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
2 T; ~- K% [! r+ x# z: b9 }
                "mday=%d, mon=%d, year=%d, wday=%d\n",
/ W  B" ~; b' @- d3 ^- U% B
                __func__,
+ @, I- c0 ~0 ~2 J7 }% U5 k8 O
                tm->tm_sec, tm->tm_min, tm->tm_hour,/ S# G- y" l$ [+ ^5 L; ]
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);  x+ a3 k+ L+ C/ t

7 S7 S2 ^# c/ k
        /* the clock can give out invalid datetime, but we cannot return* o. S" d8 b) }- a* [1 ]- ]
         * -EINVAL otherwise hwclock will refuse to set the time on bootup.3 O( ?: C& N7 W" {. Q
         */
4 ~; ^; P9 o% T* i: [
        if (rtc_valid_tm(tm) < 0)
( S9 H1 o& T: ]; b
                dev_err(&client->dev, "retrieved date/time is not valid.\n");7 l1 b: ^* ?* W. Q5 _! G1 D/ R: u

& A* [1 J% K6 W
        return 0;0 I9 t/ I% U% w* G  w
}9 F* h' i& n& v9 t1 }

; y7 z4 T/ T: _
static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)4 K; M; A4 J  b
{
. g$ G. y: g1 e* e# [- u6 d2 B; u
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);) Q! h7 D/ \6 B: B& M) k
        int i, err;+ `; m1 x6 w, q% e6 O+ l
        unsigned char buf[9];7 m( z- r" w  O; y0 u6 W5 F

. Z+ C$ x' p8 I7 C; q0 c
        dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "8 e  S  b- w8 a& d4 p+ |' s
                "mday=%d, mon=%d, year=%d, wday=%d\n",
' A  [4 r: o9 P/ Q
                __func__,1 D2 k8 }4 Z! n
                tm->tm_sec, tm->tm_min, tm->tm_hour,
1 N5 ~+ l/ x, m
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
: [4 K# W$ _2 e. i' D- I7 [
1 m8 z0 D  ?6 L9 D1 x1 T
        /* hours, minutes and seconds */
$ ~9 N  _, e! ~
        buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);' h' m+ n; W) Y' h9 u& V: i5 G
        buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);6 ?: n! j! k0 t6 L
        buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);9 f! R5 X3 F/ D7 e7 A
. A0 Y2 c8 X, P
        buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);6 g( Q" F" A1 L( F! h7 V

; E% V1 w3 O7 g$ B/ Z* x8 B
        /* month, 1 - 12 */! U& O" H8 n3 I4 ]/ f
        buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);3 V$ c& a7 }2 b! u! x4 W

7 K7 }" P- f; j* X1 z% H8 u
        /* year and century */
8 I7 T3 ~$ A) L* }
        buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);1 m" x4 H/ K9 [$ \3 }% i
        if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
7 h0 P5 q  D- s. U
                buf[PCF8563_REG_MO] |= PCF8563_MO_C;% r: G8 z. K! B) N7 x; x
+ F0 H! Q& _7 o" h" y# ~( m
        buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;4 v/ z, Q) C0 C1 E; `1 I3 X
: b6 [1 p, u. M, S
        /* write register's data */
8 V+ ^8 m. D' u
        for (i = 0; i < 7; i++) {6 U7 Z( ^  L5 L& C0 a
                unsigned char data[2] = { PCF8563_REG_SC + i,8 _+ o, V5 U0 D" o7 ?4 ^
                                                buf[PCF8563_REG_SC + i] };9 o; K6 z& m/ `5 ?6 e, L% T: }
4 |6 r: O& k  j1 }
                err = i2c_master_send(client, data, sizeof(data));. W  E; @) P6 K3 _% d' o
                if (err != sizeof(data)) {
2 V' r# q5 X" c- L6 i/ q; P9 {
                        dev_err(&client->dev,
+ s1 s/ z- W( o2 N$ ^
                                "%s: err=%d addr=%02x, data=%02x\n",
$ p) H& H, {4 t) p
                                __func__, err, data[0], data[1]);
; g- b1 @- N, h( s7 ?
                        return -EIO;' U( `! U$ L* |5 C/ ~
                }
9 G) e3 e0 C' u8 U) g4 l2 C. G
        };; q3 O4 Y1 c$ f% l; l

. q, E! ~3 s  U) X
        return 0;
; z* @) o( P* c8 [4 \2 H# P) j/ u. r
}  u, ]3 L" {4 q. |: J* e! y

5 l  ~% d- a  s$ m1 h% m4 O3 \+ L
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
8 Q$ ]1 J$ u. }
{  q8 A6 e" r/ f8 ^( ?
        return pcf8563_get_datetime(to_i2c_client(dev), tm);% V; W1 @; I  \: J
}! l! m7 d# n/ p  E% R$ G* J
% O5 r5 \$ u. d  E7 Z+ v+ Y5 D
static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
, Z4 u7 `2 K/ o+ h, u
{9 |5 z( e) Q' w; ]
        return pcf8563_set_datetime(to_i2c_client(dev), tm);
8 H- \4 E8 b" g3 i1 {& c! U/ N0 U) j
}
- s9 S8 S  m8 l) l' \& M* ^
) x$ ?2 Q9 g6 B' t! R# I; Q* N0 T
static const struct rtc_class_ops pcf8563_rtc_ops = {' [- M  {' X- H, C
        .read_time        = pcf8563_rtc_read_time,# B5 T6 A' X9 Z
        .set_time        = pcf8563_rtc_set_time,
4 D6 M8 q5 W  y+ \. d/ M8 x8 V
};0 T) I3 a: _3 M! ^  S
8 r; f# w( }  {  Y1 z7 [! ^* W
static int pcf8563_probe(struct i2c_client *client,
; b, b2 H9 r0 H+ a! x/ T
                                const struct i2c_device_id *id)
* r- J4 G: @! H0 `% h: e' X
{* h6 Q  ]2 ~, @" E$ p
        struct pcf8563 *pcf8563;# r3 e8 @8 h- [  y3 C

. R0 R( w, F1 M9 X. L2 _7 I: K+ r* C$ e
        int err = 0;
( H% H! N$ K% M9 ?* _

; p7 Y# h0 p2 R- b5 F
        dev_dbg(&client->dev, "%s\n", __func__);
. Q5 I8 d; j" [! T- _

7 z4 S0 \) Z3 |8 B  X# r. Q" {& ?6 z
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
, V9 a& e9 r  j0 g
                return -ENODEV;- F( `- w5 x2 M, R- a; |
: ]" X; z% r7 e% {, z
        pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL);
. t3 ^2 A9 g0 m2 L! D
        if (!pcf8563)
9 i3 |4 a3 f5 ]. p0 y# f; e9 q
                return -ENOMEM;
0 E3 s  U; m, n- h0 H; ?, Z
+ T4 V. F/ k! W! `7 G2 s
        dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
6 S6 _0 x, s# U  |# B7 C
) k( {* V# i- t  W
        i2c_set_clientdata(client, pcf8563);1 P9 A4 `+ s2 }# R
  {- z  F8 C0 H
        pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
0 p. p0 L3 l2 U
                                &client->dev, &pcf8563_rtc_ops, THIS_MODULE);
# F3 y2 j: H) }1 G% u
; r# V+ E! L5 q% f: v3 Z
        if (IS_ERR(pcf8563->rtc)) {, I$ a" p* k1 C' Y6 }
                err = PTR_ERR(pcf8563->rtc);
* q: D8 Y$ g; x, M2 _: e
                goto exit_kfree;  y% t$ x, k3 Y5 q  s
        }
, y3 j+ c# q' \9 P: O2 X$ M. y
! X# t  i  F8 q: K6 Y
        return 0;# w2 ]8 r4 B8 l

/ n# ~1 B' d3 e- p2 D
exit_kfree:
$ D. z9 B1 {0 O1 ]
        kfree(pcf8563);
- k& ?0 d: l" A& ~" h! o1 C
0 a% Z% \6 A. |6 G, z6 [) z
        return err;
4 y/ z* |$ E5 V* s
}
+ {0 C5 O7 R7 G' G4 J1 p1 B
& h. G# o) l# H
static int pcf8563_remove(struct i2c_client *client)
5 ]. {9 \6 @6 \% [& C
{  D- G: x+ d7 `% a
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);' j" Y& {: y7 X+ J7 T/ Y7 R
/ l5 U2 q: m" i& N
        if (pcf8563->rtc)+ Q" u0 L! R* K% t
                rtc_device_unregister(pcf8563->rtc);& Y; D) x, r. D* @+ ?0 u6 L! f9 t

( o8 ^7 y# K; ]; Y. z$ V
        kfree(pcf8563);
& k/ I' T3 q4 T" a- R% ^
- s" [0 B% t' [+ i' O2 W; W" F
        return 0;/ r: T+ C$ D4 [+ S
}5 i3 p4 ^2 |7 B% O9 [/ l. Q

! b( V0 t' X$ J, g% m. l  s
static const struct i2c_device_id pcf8563_id[] = {1 j( s% `5 t5 y! G6 K
        { "pcf8563", 0 },: O7 d& r1 t  m2 D% B: L
        { "rtc8564", 0 },
& L& n* l# O4 {8 `$ j
        { }6 n* u: \7 E2 [8 w: @
};
0 x: K& L+ w& O$ O4 H
MODULE_DEVICE_TABLE(i2c, pcf8563_id);
7 t7 P$ B+ ]7 P6 s0 s

: R0 l/ v8 ~4 m3 `
static struct i2c_driver pcf8563_driver = {
, g  I2 p6 I' y3 u+ z+ g
        .driver                = {0 S  R& D: ?  L5 ]+ n5 G
                .name        = "rtc-pcf8563",' ]6 k7 H" i; g2 l. n
        },! A7 i2 ]% I! g0 r" ?% K
        .probe                = pcf8563_probe,5 P4 Y+ d& s! ^8 y1 L2 W
        .remove                = pcf8563_remove,9 Q( A$ y% h7 Q, ~# d1 y( l! ~( Q( b
        .id_table        = pcf8563_id,
9 t4 d+ f$ _; B  h. {) Z9 \3 O& j
};
/ M3 _* R0 @# D. r

+ Y/ G0 B. w9 C+ J1 d$ [2 H5 J+ ?
static int __init pcf8563_init(void)9 {/ @# D' ~7 |! Y
{) F- ^3 m+ E" |3 K
        return i2c_add_driver(&pcf8563_driver);$ i6 {  i* h( Q% G: ~
}  w6 T4 k/ f7 t2 Y6 B
1 Z. [9 |  ?) I! }6 \+ a0 J
static void __exit pcf8563_exit(void)
  b1 H) u2 F8 m5 Z$ e1 t6 q
{" S3 J2 M5 D: E8 o1 k
        i2c_del_driver(&pcf8563_driver);
( C% b- b4 z" {2 m$ A
}
! k, r0 X6 s( V" n3 @! j6 G
1 K% y5 ~% N( k$ c3 ~- M
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");/ r% Z4 @% f" D% K- \# k, E
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");" P! n* D( Y1 k/ W. N
MODULE_LICENSE("GPL");7 {6 Q3 a' e, x9 P9 N2 ]$ p/ K
MODULE_VERSION(DRV_VERSION);# M5 T( o7 I+ v3 i6 J

! E% B% s) y3 y& J- L7 }
module_init(pcf8563_init);
6 _6 G% i  m  u  z- `4 `1 B% u
module_exit(pcf8563_exit);

: ^1 ^8 k0 H  Y9 x2 Z) t. Y8 e

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

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

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

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

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