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; @, s
static struct i2c_driver pcf8563_driver;
& j% K2 b' F8 N

2 F) L7 e7 Y7 A, U/ u' I6 v
struct 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- b
static 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 L
6 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) H
static 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 B
static 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 }( p
static 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- u
3 G& ^2 u9 ?2 s* u- x. N9 ?0 \. a
        int err = 0;
0 R- ~3 d" r  j* s$ |! s5 ~  u
3 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# M
1 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" }. B
2 @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  W
0 \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" Z
9 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 z
6 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 `% O
static 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: U
MODULE_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" i
0 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 [  K
8 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 u
MODULE_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