找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

巢课
电巢直播8月计划
查看: 91|回复: 2
打印 上一主题 下一主题

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

[复制链接]

11

主题

12

帖子

145

积分

二级会员(20)

Rank: 2Rank: 2

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

EDA365欢迎您!

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

x

2 ~( E/ \6 u8 E# ]
开发板:
各位版主、工程师们你们好:
      请教你们一些问题:
             1)在内核中配置pcf8563时钟芯片启动完成,内核启动后 /dev/rtc/ 中没有pcf8563芯片对应的 rtc 节点;
             2)内核启动过程中打印 drivers/rtc/hctosys.c: unable to open rtc device (rtc0);
             3)pcf8563芯片驱动程序的 pcf8563_probe()在整个启动过程中没有被执行;
             4)请问这是怎么回事?该怎么修改???
             5)驱动程序代码如下:
驱动代码:
! i9 k6 Z1 H, N5 l/ E
#include <linux/i2c.h>6 I! s8 \9 l6 }! P
#include <linux/bcd.h>' J8 r$ k. u' }  w
#include <linux/rtc.h>
) P/ A* b2 v7 \# L5 V+ k, l$ g
#include <linux/slab.h>, _) H- o1 E' S9 B+ r
( ~& j& E$ T: u$ \, j
#define DRV_VERSION "0.4.3") Q$ A* v$ B1 i3 K0 x7 `& H" Y
. X  b7 n' {5 e1 @7 a
#define PCF8563_REG_ST1                0x00 /* status */" g/ c' u: U* ~! A3 V
#define PCF8563_REG_ST2                0x01
: S) o# \: `: F$ B* ~. M; [8 Z( P
( I* _% e* N8 k! D% G( N
#define PCF8563_REG_SC                0x02 /* datetime */% J5 N" Q$ I/ t
#define PCF8563_REG_MN                0x03
$ R% |+ v' F. M' E" N! R# x! U
#define PCF8563_REG_HR                0x04
$ N2 n. U, g- `- D6 Y5 I3 h5 E
#define PCF8563_REG_DM                0x05
" E& \5 V( P  m3 D0 M
#define PCF8563_REG_DW                0x064 S. L- D, F4 X  u4 ]' c! D" x
#define PCF8563_REG_MO                0x07
* A* o8 k6 r( p% q( y+ a/ L
#define PCF8563_REG_YR                0x08& I) P3 a  C. l1 j% n
7 z$ D, N( {" H
#define PCF8563_REG_AMN                0x09 /* alarm */
. ?  X$ \: B. F( q/ x! `0 d+ I( s
#define PCF8563_REG_AHR                0x0A2 r' E9 v- _3 g
#define PCF8563_REG_ADM                0x0B
. S8 d1 V# F2 v# p
#define PCF8563_REG_ADW                0x0C
  Y" p$ K9 b: G# ^8 M+ M4 v

4 n' H% P5 C) r
#define PCF8563_REG_CLKO        0x0D /* clock out */
% O1 b% h% @, c* v+ `8 R& B
#define PCF8563_REG_TMRC        0x0E /* timer control */
5 v, ]" x; F/ E, J; w# l, L
#define PCF8563_REG_TMR                0x0F /* timer */. O: p& i+ Q% j9 Y

5 p& k: T- T' h: x8 a0 P& O
#define PCF8563_SC_LV                0x80 /* low voltage */
* U9 Z) e) |& O3 i+ ]2 e
#define PCF8563_MO_C                0x80 /* century */
9 r( [; O) q5 o/ W: s* M6 s/ U

, T, j( H$ n4 s
static struct i2c_driver pcf8563_driver;. g# C6 |( |8 \9 E
" K; N. R  T" S" j, [2 q
struct pcf8563 {
7 l- a/ ~" }0 f
        struct rtc_device *rtc;8 r5 B0 y: h2 V1 z
        /*
' h4 X% \& y& Z- w: ~7 a
         * The meaning of MO_C bit varies by the chip type.: q, `$ \& k6 S" i6 R3 O
         * From PCF8563 datasheet: this bit is toggled when the years
+ H' b# @; J0 K) t8 n1 b
         * register overflows from 99 to 00
/ P$ W% N6 p8 r2 ]
         *   0 indicates the century is 20xx# E4 }; X6 M# C* K" E. L1 `
         *   1 indicates the century is 19xx  K+ K) \5 E8 F& b( \$ E
         * From RTC8564 datasheet: this bit indicates change of
) D4 H8 t! u, G& X* J, E0 E
         * century. When the year digit data overflows from 99 to 00,
: {4 `3 d: \1 V* k
         * this bit is set. By presetting it to 0 while still in the
; H% W1 @9 @8 x% k  V$ r/ q, o
         * 20th century, it will be set in year 2000, ...
) c. P  ]! l5 S2 J! T
         * There seems no reliable way to know how the system use this
2 {" l! a" I% b6 j6 p/ h
         * bit.  So let's do it heuristically, assuming we are live in' m9 W, v# |9 e: j& p
         * 1970...2069.
6 U: c+ F3 u3 f1 ~/ c
         */
3 t# @- y. h& `+ \/ \. G
        int c_polarity;        /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
# b8 @, e" c, B% F. A, X$ j2 D
};" p8 p7 _. B+ E, g' f' m% D

% _4 A& k* ~. `+ Y/ k& n4 @
/*. M0 x: A& A, E! R, M
* In the routines that deal directly with the pcf8563 hardware, we use
8 t' E9 O( a7 X3 P* q
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
4 H8 F$ C( x5 R8 o1 y
*/+ i; w) O3 f! C8 C% t
static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
' `* S& h8 R2 C! M/ o
{
) ]1 X0 h) A9 l" H6 F$ G
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);" `- f' E! ~4 B1 @- p, E& q8 A! n& z
        unsigned char buf[13] = { PCF8563_REG_ST1 };& C+ ?, L+ Y" h7 i( n3 v  @* f
* f+ ]4 r! M1 E; p0 Q+ y; p3 r0 S
        struct i2c_msg msgs[] = {
. F& z# R$ W& Z* }& H- y
                { client->addr, 0, 1, buf },        /* setup read ptr */
" Y/ \' P, p4 I) P2 o0 _  s
                { client->addr, I2C_M_RD, 13, buf },        /* read status + date */
2 [- j# |; X" b# S, Q& G. X- P$ |
        };
6 y) X( ]4 j! _( J; m0 E8 R  G; v
3 ?& H& Q" `- m
        /* read registers */
- Z% J; I9 u% m% m4 s4 w/ B
        if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {  E; P1 X6 O# F" y' @! }1 X
                dev_err(&client->dev, "%s: read error\n", __func__);
2 \" }( T+ n! z9 Q, u
                return -EIO;' M7 G; t' ^! t. A7 h3 L5 u
        }3 ~2 a( W. T: Y6 a* L
! ^1 {- a) P  f) M* B
        if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)
% V+ u; Q3 s& {9 ~: J
                dev_info(&client->dev,
( J2 h$ N1 Q" }( R. D' q
                        "low voltage detected, date/time is not reliable.\n");. O7 n, `# F2 a7 R: _  ]
! x1 Z( {+ _/ V! {% X
        dev_dbg(&client->dev,/ o3 N1 \* c, x" E' X8 @
                "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
" `1 N& A9 [' L* C: i
                "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
. i- E; P: u7 A, c' S9 S/ H2 t$ A
                __func__,
% i; [7 c5 V4 W4 D7 ~" n) q/ |
                buf[0], buf[1], buf[2], buf[3],8 l" B: ?7 m' h- Y8 ^
                buf[4], buf[5], buf[6], buf[7],
( H6 J  k& W. Y" h  V
                buf[8]);
  ]5 [- d$ d% u! ]# w
# ]3 T- V& l8 c6 n

$ ^# u* `) L# O! L$ ]
        tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
, i5 y4 a' Y6 T
        tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
0 l" s- }% [1 l! N. {# n$ M" Z! n
        tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */* C8 A! C9 U5 X" O, U8 H$ O
        tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);  u" M% G8 q0 f- B- N/ ?
        tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;( L2 T; c6 H, t: T! C: z. u4 ?
        tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
7 o5 Y6 F  F/ A6 e  A8 [/ {6 n5 F
        tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
6 S6 z/ e* M+ `
        if (tm->tm_year < 70)7 L- w0 S5 N0 K# V- s4 n9 C: H" j
                tm->tm_year += 100;        /* assume we are in 1970...2069 */& [7 K- b- B9 m9 C7 \/ j) Z
        /* detect the polarity heuristically. see note above. */
" e, v* Z7 G9 E( t1 k, [
        pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?: D+ u/ m+ e- g
                (tm->tm_year >= 100) : (tm->tm_year < 100);
1 b& E0 U# U% l5 \9 h

* I, D# ^" \$ L+ \
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
0 \" t0 B5 i$ ?; k( U, E
                "mday=%d, mon=%d, year=%d, wday=%d\n",) g+ k% A; V3 V( f- G" f
                __func__,. k1 W4 J6 L( d* l4 Z
                tm->tm_sec, tm->tm_min, tm->tm_hour,! o4 V& @% k& _1 I
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);7 x1 h0 H2 S9 M5 W8 n. `; {; o
$ F0 s5 J. g, h- {% i
        /* the clock can give out invalid datetime, but we cannot return
) u2 B1 }, H  d+ _4 K/ i
         * -EINVAL otherwise hwclock will refuse to set the time on bootup.
3 H1 ]$ L( \  n# ~. v( Z& Y
         */5 ]0 ^1 L0 F# z' C/ ]- i
        if (rtc_valid_tm(tm) < 0)
4 j8 x: p7 G  e. ]( s2 a; y
                dev_err(&client->dev, "retrieved date/time is not valid.\n");
: d% }( B" J* F# V. f
/ a7 p1 J9 x! j& @  C' j+ Z% X6 ~
        return 0;
: [1 K; v& v1 Q" `% h% T/ ?
}
3 v2 v/ B3 Z3 [# `# i+ U7 R
3 W  [8 W  H3 X' x
static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
" K1 y' J5 }. i- L' j3 P
{
+ j+ ^5 x' l8 Y3 i# e; h5 ~3 i
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
; G( O# X+ E2 g6 B" X& [
        int i, err;, A$ W, B6 h4 h! i1 z' D! A
        unsigned char buf[9];
( K3 C* G0 m2 B" P( p$ L

- F. b: u, A+ l7 u2 c
        dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
/ a! h: _1 p$ S& R( ]. }
                "mday=%d, mon=%d, year=%d, wday=%d\n",
: V. e5 m! O) \* S2 R, t7 D% m
                __func__,
5 d' `6 s2 b) m3 b0 M) z' J+ f
                tm->tm_sec, tm->tm_min, tm->tm_hour,; @3 g$ Z7 r8 ]7 b: u9 M/ T
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
% ^8 B7 ^+ D! P

3 Y6 l  {( o$ `/ e9 m
        /* hours, minutes and seconds */: M- j' j: N# B8 q
        buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);  s, y) i4 V. N/ C
        buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);6 q2 {% s$ }0 F( x. _
        buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);9 d- X! Q$ c* n. ], P
. X  t8 Y0 Z+ f$ ]$ j. |
        buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);9 M) u' l! L) n# {' D# U& b% g
. B9 J/ S8 _- q
        /* month, 1 - 12 */
5 S( z6 x8 w( s( @( ]
        buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);
: B+ C# J1 K8 N
3 u# V) [4 ]3 V4 E( r( N2 |" c# V
        /* year and century */
9 W' V! `( R. N# g
        buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);4 F. b; \6 E9 {) F
        if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))1 O* K2 s0 e9 ~) v" h3 I6 ~
                buf[PCF8563_REG_MO] |= PCF8563_MO_C;
) _3 R9 Y. o2 [9 {
! K2 B8 H* \9 x5 P0 y3 ]
        buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
8 S: j. t1 C; P4 t( {5 T1 g

5 s- C9 X; |0 F( M. P' m
        /* write register's data */  c6 \; k" F& B
        for (i = 0; i < 7; i++) {! m. h  s6 J2 v+ p" Q7 T9 U/ N
                unsigned char data[2] = { PCF8563_REG_SC + i,$ D, q, z' }8 D+ }
                                                buf[PCF8563_REG_SC + i] };  ~7 d  @; y  ^/ H, x

7 n+ h- K( |& j" S' a8 m) M
                err = i2c_master_send(client, data, sizeof(data));0 x& M: `1 N5 T0 s* p
                if (err != sizeof(data)) {
. W) M4 k5 z* }, v
                        dev_err(&client->dev,
2 I2 t( T: F6 f/ f- R4 @
                                "%s: err=%d addr=%02x, data=%02x\n",9 w1 v# w; S6 j! G+ z
                                __func__, err, data[0], data[1]);; q+ w4 e2 i5 J, ?- I7 f
                        return -EIO;4 v9 H4 b- ^4 e
                }
7 Z! z) s4 \5 D7 W5 X# ~2 u
        };
" v0 g% W! }# r$ F' w
5 ~; Y3 A4 i, h
        return 0;4 {/ Z# [9 s' s* [$ V4 ]7 u/ m4 C! j
}# z" a( s1 Y) `0 L

' W$ }5 @% U2 a( ?3 E7 F
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)) ^, e2 i" o5 g2 p
{
+ U" H% b, u; b4 @1 P* N
        return pcf8563_get_datetime(to_i2c_client(dev), tm);/ w9 C: X0 c8 a8 D! {. _9 m/ a
}
% m# w$ y* S4 f" ?

9 R* L: |% ~, C
static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
" k  ~4 _5 M, P4 S
{
; o* J4 ^3 y) M. E
        return pcf8563_set_datetime(to_i2c_client(dev), tm);
8 R3 @. B5 T5 w6 [! V
}" v6 {) n; ~) F* q8 d
6 C& z% u9 E; v! v) X2 n% n
static const struct rtc_class_ops pcf8563_rtc_ops = {
6 B4 s7 ]0 W: m" j4 i* |
        .read_time        = pcf8563_rtc_read_time,  s, B6 a3 P3 G! S5 o  r1 u
        .set_time        = pcf8563_rtc_set_time,
# }7 r& h& D- l5 T
};3 F& W1 w* ]# m& ^& y* G5 c, i
  i' V* A' C! R1 ]9 g
static int pcf8563_probe(struct i2c_client *client,
+ o4 ^. [# {$ I! _8 Y+ q
                                const struct i2c_device_id *id)5 W$ q0 ?5 T: N& ^
{6 @$ }8 u4 p0 N0 O" w: Z
        struct pcf8563 *pcf8563;/ x! A- g& k  c: C7 `$ V  i

9 e# [7 s+ u% {9 w. N
        int err = 0;
' z; n  U; ]9 h" I! A( ]( t0 X" ?3 Q

1 v( r- f: h2 ^' w2 `
        dev_dbg(&client->dev, "%s\n", __func__);7 J( G" g* U* w4 E8 L
. @' w* u, g" A, x
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))! O& U; V* h5 m1 l) ]
                return -ENODEV;. c4 ?- J4 ?7 [+ ?* D% c4 f& C

3 \% e' t' h! [- z- o7 n
        pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL);
$ m$ h* h: I  r
        if (!pcf8563)/ j4 F, W. P, }; R$ `, _" d
                return -ENOMEM;3 R/ j! I6 }; ~6 V. \, Q

/ \: g% @) ^' }# N
        dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");9 s0 w, k" Q( M; }9 p& K/ t
! v' @- G: D. k! ?; e1 P
        i2c_set_clientdata(client, pcf8563);6 O& p3 g. B, W8 ?3 r  v

; k9 u* i1 Z" P& |7 c5 V
        pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
9 `' y3 F  m( ~- ?& \
                                &client->dev, &pcf8563_rtc_ops, THIS_MODULE);
: a  c' R& K' V) J+ D, M" J

1 c) l( f3 \# a' w4 O0 i
        if (IS_ERR(pcf8563->rtc)) {+ S7 E" @0 F) q6 T: b/ J* ]
                err = PTR_ERR(pcf8563->rtc);
0 k# Z0 Y: y, F7 B4 Q' u, n5 j# n
                goto exit_kfree;
: u$ s# C3 [. b1 w! X
        }& k4 I: j, r1 r3 L
5 E# L2 T7 Z/ ^! A
        return 0;: q. h" E, C) i4 C$ W1 q: p# }
/ a  r& m1 s4 Q& _4 c# e# K8 K6 Q
exit_kfree:% ?- N8 G6 l, E+ H* F# I2 I  z  b) j
        kfree(pcf8563);! t$ t6 f. U8 r% B& w. N0 L
* o, S* t2 E& o* \
        return err;
# X$ Z# ^, X/ Q+ j7 v  w9 {
}
1 w: f  B  |5 y; U9 @' ~( O) K

- I! `( v' X) t! U
static int pcf8563_remove(struct i2c_client *client)
( I3 l. B. c$ ^9 p( _- B
{
5 |# t/ T5 W' ^) n. `% W/ d
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
( D. B- g" T; F+ l2 O
) R; ^* Y" x' g" |7 m+ l  i! }
        if (pcf8563->rtc)
' k) i7 C* V# C2 a% n
                rtc_device_unregister(pcf8563->rtc);
2 m# {" p$ s! Z- O1 v

0 s  k# N) l6 U6 h1 Q1 m8 u4 e
        kfree(pcf8563);
- ]5 M* k: O0 Q* l$ M

, Q( x4 u5 [1 d0 o8 |
        return 0;
% o; X# r0 n: m. W! L4 B) b2 }
}
4 l: o) L! c# I2 Y7 ?( b

0 g2 H! x  H7 T& Y8 m! |4 d
static const struct i2c_device_id pcf8563_id[] = {
! {0 e: ^' Q8 U  d
        { "pcf8563", 0 },5 q5 C( D/ O! e6 R  v
        { "rtc8564", 0 },0 @& Q& Z( N3 Z
        { }
3 x" q( Q; v4 `2 Z$ t
};
9 Z6 W; ~, R* k- [
MODULE_DEVICE_TABLE(i2c, pcf8563_id);: y; E& \5 G/ @$ E8 Z
9 O3 T3 A, n, N( g7 q  |
static struct i2c_driver pcf8563_driver = {0 q$ ?- H1 [& Z1 P' N) G; y
        .driver                = {
4 p7 k# K. f( ]3 H* t! K$ L
                .name        = "rtc-pcf8563",
. N  Y! d7 ?+ K/ a* k3 [  ^
        },
6 e% @9 a4 c; ^; h
        .probe                = pcf8563_probe,2 v6 A  Q0 f- N4 m7 P. d8 R- {
        .remove                = pcf8563_remove,8 Z5 _7 e! e: ^) S- b9 X" Y, w
        .id_table        = pcf8563_id,% Z2 h" Y  H' K- P, r
};8 D: y5 [; K6 \- \7 B4 T4 u

1 |- i8 G  v5 b# G
static int __init pcf8563_init(void), W4 [3 j& `1 }4 Z$ ~) \
{
4 j: l# Z. O% [9 _; N* s
        return i2c_add_driver(&pcf8563_driver);
3 n2 D# a; a* M" i
}
% U1 W. r/ c- h+ R, {
) f6 X4 \# {2 q' ?+ S9 O
static void __exit pcf8563_exit(void)3 F, p' P; U5 F  x1 W
{' a# `- y, q" w6 j# u
        i2c_del_driver(&pcf8563_driver);
+ ?! E' T; v+ s4 u6 u+ W
}
1 r& _& {- B% n" E4 \

# Q5 H  L: A  T$ y- U
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
) g# F$ C: n/ a- Q1 O3 {! ~
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
" e+ ]  `# e* T8 ]) @
MODULE_LICENSE("GPL");8 ^& W: C8 O$ s
MODULE_VERSION(DRV_VERSION);. X; ^1 N: s. O2 g% G

( c, M' C8 D7 \9 S) N7 Y
module_init(pcf8563_init);+ X9 O" r/ g7 a: }- v, e& e
module_exit(pcf8563_exit);
7 n. F5 ?) |$ F
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 支持!支持! 反对!反对!

0

主题

7

帖子

36

积分

二级会员(20)

Rank: 2Rank: 2

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

3

主题

135

帖子

2203

积分

四级会员(40)

Rank: 4Rank: 4Rank: 4Rank: 4

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

本版积分规则

关闭

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

巢课

技术风云榜

关于我们|手机版|EDA365 ( 粤ICP备18020198号 )

GMT+8, 2024-9-17 04:35 , Processed in 0.078480 second(s), 35 queries , Gzip On.

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

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

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