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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
% K) G+ E( |' r  E3 k: i# q' |6 y
开发板:
各位版主、工程师们你们好:
      请教你们一些问题:
             1)在内核中配置pcf8563时钟芯片启动完成,内核启动后 /dev/rtc/ 中没有pcf8563芯片对应的 rtc 节点;
             2)内核启动过程中打印 drivers/rtc/hctosys.c: unable to open rtc device (rtc0);
             3)pcf8563芯片驱动程序的 pcf8563_probe()在整个启动过程中没有被执行;
             4)请问这是怎么回事?该怎么修改???
             5)驱动程序代码如下:
驱动代码:
2 u& H4 g/ M' U; W) J( W
#include <linux/i2c.h>
8 J# w! K% i8 x' R( G
#include <linux/bcd.h>0 x/ p$ g5 n2 v7 B3 J
#include <linux/rtc.h>
% z! `7 E# K2 I+ M5 N" ?( ~( C
#include <linux/slab.h>) q) t( E# R4 K$ `3 h

$ x! l3 O! l$ Q7 H+ {
#define DRV_VERSION "0.4.3"
) g$ ~; Q  ]0 s2 E

1 M1 q6 y/ p4 B5 Z
#define PCF8563_REG_ST1                0x00 /* status */
0 R3 j( a- x8 k
#define PCF8563_REG_ST2                0x01
) w' t/ y( }( S; N7 `( q7 @
6 J$ s  z. d) Y- U! X5 P8 }
#define PCF8563_REG_SC                0x02 /* datetime */( h2 a8 R  F$ u. \7 A
#define PCF8563_REG_MN                0x03
; A) g4 }, ~- }+ ?3 ~, [
#define PCF8563_REG_HR                0x04
* U( a$ c6 g' h, r
#define PCF8563_REG_DM                0x05
" T; Q' G3 n9 H: m: L' z
#define PCF8563_REG_DW                0x06  u7 _5 S7 ?; \0 y* l
#define PCF8563_REG_MO                0x07+ V' h* `' I2 y0 ^- u3 p
#define PCF8563_REG_YR                0x081 W  b9 H" [3 J7 w! K" V* x$ e

8 y6 Q/ g* r3 U2 X, c
#define PCF8563_REG_AMN                0x09 /* alARM */4 r! K8 r/ A7 z5 o, ^
#define PCF8563_REG_AHR                0x0A. Y) d$ v: X1 v6 t5 c, ^
#define PCF8563_REG_ADM                0x0B0 h; m1 m$ v7 f! M  G& O5 u
#define PCF8563_REG_ADW                0x0C2 G$ j& r! x& x  V+ d& _6 [( ^. O

/ k7 R0 e- l0 p! v. k: s2 J
#define PCF8563_REG_CLKO        0x0D /* clock out */+ Y. F; v$ I/ P# y' |1 \; s
#define PCF8563_REG_TMRC        0x0E /* timer control */
7 v. Z1 R5 Q- j, H8 k
#define PCF8563_REG_TMR                0x0F /* timer */, G, y9 u+ X  s1 i
2 }  v* M. N$ I1 ^2 i
#define PCF8563_SC_LV                0x80 /* low voltage */0 c* Y# H4 L9 T* T! I- C: h) H
#define PCF8563_MO_C                0x80 /* century */
; r% X) u- A3 Z) M7 ]& v# N
4 F+ I/ s: _& F- |. S
static struct i2c_driver pcf8563_driver;! y4 F. Z0 x- n$ A
3 T/ ^& e, M* B% F. X
struct pcf8563 {
6 G3 U; V  {% a, j5 d
        struct rtc_device *rtc;2 U8 A4 ?1 m8 K/ j% h' Q5 C  J* v
        /*
- |) L4 D+ A9 n
         * The meaning of MO_C bit varies by the chip type.
+ c7 x. L5 }7 q- [+ b1 z2 ^1 C& n
         * From PCF8563 datasheet: this bit is toggled when the years
5 N: |6 o9 ^- B- c' z
         * register oveRFlows from 99 to 00+ Q+ m% J/ o+ ?1 {$ M: e
         *   0 indicates the century is 20xx0 w  s8 m, U5 o6 z! R
         *   1 indicates the century is 19xx  A. Y3 C. d: W/ J/ r4 F
         * From RTC8564 datasheet: this bit indicates change of. q* S4 \! J# J1 S* L
         * century. When the year digit data overflows from 99 to 00,3 {0 h) I# \3 m) X% ]: ?+ H
         * this bit is set. By presetting it to 0 while still in the
) p/ a; J% P) z5 ^
         * 20th century, it will be set in year 2000, ...6 U9 c7 f5 L! W
         * There seems no reliable way to know how the system use this$ B$ d- R" H- u7 B& d
         * bit.  So let's do it heuristically, assuming we are live in/ @  l1 }/ m8 v. C2 p# P
         * 1970...2069.9 L5 `! N& }% m* _% j/ Y
         */
& f( M- K" {* E# u) y$ P9 _+ a2 v
        int c_polarity;        /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
) l; @- E" I: o4 i
};; h0 @3 g- g+ E- L0 V
. f& c( i$ H/ i# A
/*
# T+ k, b/ t% C% a) i
* In the routines that deal directly with the pcf8563 hardware, we use% V7 B$ e/ N( L! z" ?; T
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.5 m1 e9 }) m; l5 b1 H  g2 N9 `
*/1 [7 D) r' \: @) i4 h1 q1 Y6 u4 i
static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)7 x  C; Q5 f1 t1 m+ g
{( R0 v" _6 a. K; _. q( R, a0 j
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
' T3 y  \6 ?3 v9 |
        unsigned char buf[13] = { PCF8563_REG_ST1 };+ G: S0 t1 t  U7 m4 j- x5 d# k1 \
; s; w  C, m! e  P& \
        struct i2c_msg msgs[] = {
- c1 b" |: |, ~! a& n5 s
                { client->addr, 0, 1, buf },        /* setup read ptr */
# [, D4 n  [+ c$ X! [8 v' D8 z
                { client->addr, I2C_M_RD, 13, buf },        /* read status + date */
% E1 V4 V- h/ f7 f2 m# u
        };* ]$ d6 A1 c0 e" g' A4 w! C
8 m7 \9 v& [' v) m0 k
        /* read registers */9 A' v3 w  w, |. m/ U. Q8 ~
        if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {; b5 |" i/ f' x/ Z! j$ D# |1 x
                dev_err(&client->dev, "%s: read error\n", __func__);5 A7 q! j0 K  O. s/ [- `6 M. w
                return -EIO;+ G, t5 u- Z$ [: L! P
        }
7 x6 b- M8 s9 K# Y/ X( L
# |4 l! C7 L" v3 x% \# B
        if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)7 n: u6 S0 o4 A- U7 Y- C7 v" v* G
                dev_info(&client->dev,
+ B6 j5 t0 q5 Z! @9 D+ C4 d
                        "low voltage detected, date/time is not reliable.\n");
2 }/ d! W9 }+ g, h( v' B

1 r8 F' p. u4 i& I. f! Y) S7 r4 M
        dev_dbg(&client->dev,
" E" p) Z6 H) E4 |: W
                "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, ") H, ~5 G: y. J
                "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
; o) u9 `6 j! I& Q  d
                __func__,
% U0 A# |0 }0 M+ v/ y; ?# E
                buf[0], buf[1], buf[2], buf[3],
. y+ F7 A* a" v5 \. h* V7 b
                buf[4], buf[5], buf[6], buf[7],3 `% p8 P4 o3 P) O
                buf[8]);( t* `; c$ u8 a; K& u
- a2 _" }1 w  m6 T5 ~

  f+ s8 k- B9 ?& F0 I" L. |8 L8 U
        tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);% J$ t* K, @  K6 l/ B9 _
        tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
) h8 x+ K$ q1 K
        tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */- q# V: p( x, G+ }% ]4 w; ]: ~9 R8 g
        tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
8 h% w5 T+ G% x' D8 ~+ U2 t1 G
        tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
5 `- _/ ]$ A6 M- ?( W7 q8 D2 w- ?
        tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */0 E5 f2 B1 v1 Q
        tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
0 g7 L# M" g. B' J
        if (tm->tm_year < 70)
' g/ O8 P( l$ @6 u2 C; M4 `4 [7 l
                tm->tm_year += 100;        /* assume we are in 1970...2069 */
6 j2 R! G. p) Z) \7 B/ L& y! }
        /* detect the polarity heuristically. see note above. */
2 F: F! Y0 l- D5 N( T9 g
        pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?% l/ |3 Z, J! K' X1 O- B" U
                (tm->tm_year >= 100) : (tm->tm_year < 100);
2 c& R3 v, R: z# h  M/ D
3 T( u/ b" u( Z. i4 g8 Q+ C9 W& O9 h
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "5 ]8 n% `" _2 \
                "mday=%d, mon=%d, year=%d, wday=%d\n",9 ^# d" S  y, b; n4 m7 d+ o8 }
                __func__,
& w  z  J- @4 T  ?  l+ T# Q, J
                tm->tm_sec, tm->tm_min, tm->tm_hour,/ s2 e2 h" Y& G- G
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);/ O( _. f  d% f" e
7 {3 k# r+ C* E/ `: Q9 Q- {
        /* the clock can give out invalid datetime, but we cannot return
. ~7 U' ?+ \( O: j7 R
         * -EINVAL otherwise hwclock will refuse to set the time on bootup.
, N# [) c( a) j) w- k+ n! a
         */4 a) w" {7 m, B$ P6 o
        if (rtc_valid_tm(tm) < 0)
9 B8 b- y( W- z: c( l& b8 r
                dev_err(&client->dev, "retrieved date/time is not valid.\n");
+ L7 u$ d4 Q7 z; Z5 M

. D; e- z6 s  Q$ H
        return 0;
4 D4 y$ T' G' W: l/ D( m
}+ H" Q7 b5 N; S: m# D$ I

& x0 q1 {& S9 d3 Y
static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
/ `- E) x. z, F4 K/ o% i2 {/ A& S
{9 {' Y3 _8 w  v' d5 V
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
4 \! n# s1 z# |
        int i, err;
3 r) [1 T/ [$ y' W& e( ]' [) S
        unsigned char buf[9];/ n. N0 Y) T7 c/ F% ?& ^  F  r
5 J" ]; Z; P# k; r! x' J7 M
        dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, ". Y( G: }1 R6 i2 Y
                "mday=%d, mon=%d, year=%d, wday=%d\n",1 N) E7 k$ q' F. |2 b7 B
                __func__,
  b1 ?0 o2 K+ ]
                tm->tm_sec, tm->tm_min, tm->tm_hour,' r0 N% ?  b" C# J
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
3 \3 D5 |+ A3 P

" ^' j' y1 ?$ S7 r
        /* hours, minutes and seconds */
* Q1 W& e& k! |
        buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);' f4 j2 Q& |6 o3 w: Y3 _% u# z- L( Z
        buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);1 {: [7 a4 k7 g" V0 J% j( r
        buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);
$ G! V+ r% ?& l6 U

1 `/ t5 M9 A" M' \8 |* @
        buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
7 C6 P+ w  ]1 W

: W) c9 K7 V: m  C3 I
        /* month, 1 - 12 */
4 i4 k: j: W; Y3 Z
        buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);
& B+ H% `  K! ~0 H$ J
) d% H) x( `" _" ^  T8 B. F. K
        /* year and century */9 v7 ^) i% v2 F  l) r% E
        buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);: v9 {0 ~' ~  ~  }. b9 H3 Y
        if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
' P2 t) b7 D. `% n4 S2 x8 d
                buf[PCF8563_REG_MO] |= PCF8563_MO_C;
( _  O9 q) C1 d6 g
; m9 _) n$ T! z0 V2 q2 |
        buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;( r+ y7 A% X$ N9 s; U5 S
; c$ U: L: B6 A% k$ Z/ x$ x; G
        /* write register's data */
" k; q% Z6 }& J. O
        for (i = 0; i < 7; i++) {% \4 L; b5 D( \: ?5 Z( K9 _$ C% i: g
                unsigned char data[2] = { PCF8563_REG_SC + i,
8 A. y! F8 K( O" l
                                                buf[PCF8563_REG_SC + i] };4 K6 K: c9 F7 i4 i
5 i; B. {* C/ }1 [# C. e  E+ P# s
                err = i2c_master_send(client, data, sizeof(data));
; |* u9 y8 @- I5 Q) Q
                if (err != sizeof(data)) {
/ v) ?% `( ?8 o8 Y0 P" P3 c
                        dev_err(&client->dev,
9 ]2 t% |8 }; K' C- r* C1 }/ f8 `
                                "%s: err=%d addr=%02x, data=%02x\n",0 H& Z/ }( u0 ~) o
                                __func__, err, data[0], data[1]);* v5 W0 v# `' N
                        return -EIO;! a% U1 O& T) p( Z7 m) Z" |, O8 Y
                }
6 L- j8 `8 K7 n4 p3 v7 @
        };0 t( w, Z" K+ l# c. r
0 ^+ {1 d% Z: Y" w  g
        return 0;
# H  F, g( s" B) X- ~
}
: g" a; y8 C2 P0 s4 G$ i7 V( x- c

" X6 q9 m2 [. F5 m
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)3 K. P% O& K1 r5 b/ Q$ o1 O
{2 O. j0 B6 Z8 P
        return pcf8563_get_datetime(to_i2c_client(dev), tm);
% ~* _" O& J- j7 Z+ z
}
8 s/ z" ?7 _( F  ~6 J5 W' y7 D. _
  F; l# U( u  c  `) a4 F6 {
static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
9 n5 E5 Y- A, s* @" b" C) P
{9 G. V9 B9 ]0 [, A# U
        return pcf8563_set_datetime(to_i2c_client(dev), tm);5 A  [/ \, t+ ]# v- U+ q  a
}6 h, l5 y6 a, ~8 y) D
2 ?( C9 U0 r" k0 O  P: K# Y# [
static const struct rtc_class_ops pcf8563_rtc_ops = {
% u7 j$ u$ q+ ~! Z  Z( N( V- r4 K) ^
        .read_time        = pcf8563_rtc_read_time,: e" g0 ~. Y9 l6 @$ S% J
        .set_time        = pcf8563_rtc_set_time,
, J7 z% b: z- B) x1 L
};  x. J' R0 R! P% |5 I& Q
; q& p! J! \$ X% I
static int pcf8563_probe(struct i2c_client *client,# a& m3 |( G5 e; Y
                                const struct i2c_device_id *id)
& w' {. q% x* K8 l
{
$ P* z1 ]8 p2 r8 \' P  T
        struct pcf8563 *pcf8563;
; L% ~- f7 y2 @1 E: Z/ [: P
9 z; q4 s! N6 ^
        int err = 0;; {0 e* z) a. Z' m! }! _: Z
4 E! J1 \) _5 C
        dev_dbg(&client->dev, "%s\n", __func__);2 C; c' B7 X; ]( t. c* N

+ S$ c; K5 h7 h5 K2 m
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
: ?9 g( b7 {/ h. L6 D: R
                return -ENODEV;
/ I7 Y+ N+ _" S* g) C2 ?2 m
- O& L8 x$ N& k) Z/ M! s! ]: W
        pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL);! w7 y; h- G" _% J: n
        if (!pcf8563)& t' p$ O& [. w" I* d
                return -ENOMEM;
9 n  A; U) c& C  i' [/ j1 o# W
1 u; ]; T* L$ q* g
        dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
# M5 ^3 z4 w$ d* {! }- X% g. j& o

) E. i! A1 g" J
        i2c_set_clientdata(client, pcf8563);6 \, {2 q1 P; |. b/ ]

  p8 C6 y8 i" p( G5 j4 }/ Z
        pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,2 H, p; A4 v9 ~
                                &client->dev, &pcf8563_rtc_ops, THIS_MODULE);
. E+ q6 t7 v8 i0 }$ W
8 m* _+ [  J* J( r; `) c2 i0 {
        if (IS_ERR(pcf8563->rtc)) {4 d3 o* E/ g7 g3 p* E+ ^8 r0 x0 H. p
                err = PTR_ERR(pcf8563->rtc);$ F& z- w1 E. e- r6 a+ P7 T2 {
                goto exit_kfree;
. H  i" _5 I& r' C( d( C
        }# q  I; i' S% ]  G
0 c  M9 Q# N8 u8 t; I
        return 0;
' U. M" S  v" f% B4 a

$ I0 R8 L- {# U- j2 r
exit_kfree:3 l% N! O# g2 C: I7 r, U, h' g7 E
        kfree(pcf8563);9 M) s. k$ W" q
0 W* Q$ y/ t# n( S, D0 \
        return err;
5 f; y" v* y- g! `! N( e5 S
}& D/ v0 @- x+ x) x9 b5 w. ~

: t! D& O& w+ w* b5 N9 n5 x
static int pcf8563_remove(struct i2c_client *client)
& g& P, r% c6 s: g5 k  \  @8 i
{
; V+ k# r+ P  N+ c
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);; I  q* a1 k5 ?, A1 g
3 c" z/ s1 f5 M: L% o7 a; z* x" `
        if (pcf8563->rtc)7 Z. d/ F9 Y# ]5 F* e% k4 c, s
                rtc_device_unregister(pcf8563->rtc);
- d% \0 V" I# I* ?0 j
8 l! V# ~5 d% J4 u: L6 k6 K
        kfree(pcf8563);
* }+ Q7 g# k" ~
% s6 o+ `$ @' \0 S7 D: z8 k
        return 0;; z& Z$ v# D9 `9 x( Q( Q; o
}5 h# ^9 f1 F) Z4 u
$ t9 `( J+ m% m6 f7 R
static const struct i2c_device_id pcf8563_id[] = {
" V" O1 i4 g" I9 T( R
        { "pcf8563", 0 },# @/ f) [* d/ F& U6 P
        { "rtc8564", 0 },
9 k, Z$ V2 j% G  c
        { }7 Z1 N, c. W3 c6 B4 N
};
8 T" {- q# l7 y! W
MODULE_DEVICE_TABLE(i2c, pcf8563_id);
# J2 `6 J0 M: @. W& I

; a# l1 N  L0 q* I
static struct i2c_driver pcf8563_driver = {5 X% p1 x# Z  m! a! w
        .driver                = {
- f6 @! U# u+ a% Q0 E% \( y
                .name        = "rtc-pcf8563",
7 S6 U' a4 R8 N' M! d. v" L1 \% l
        },
1 m/ i6 M* w! D8 ^7 \; p* ~
        .probe                = pcf8563_probe,
! g% q* t  O! x3 ]
        .remove                = pcf8563_remove,0 ~0 w3 G$ {* \7 I8 p& e/ E5 r
        .id_table        = pcf8563_id,' B9 ]  h2 w: x0 @0 l. E9 h# k: _
};# F) k1 s$ V8 s% k: n; N

6 a3 I" u  h& |) K3 y
static int __init pcf8563_init(void)
/ A" ?; }3 m7 J* u1 U; x
{+ H( S& Z, L( C- k4 I
        return i2c_add_driver(&pcf8563_driver);
/ W& n* C/ o' k2 L8 Z/ [
}/ M" G- t, i6 |+ @  p/ ?+ {% J

5 z" n. a; v* ^; p5 ?! h
static void __exit pcf8563_exit(void)
9 n( a2 j$ z' J  @' g# t" E/ k
{' F) h7 F# k8 X1 f% P1 Y
        i2c_del_driver(&pcf8563_driver);
/ M0 @  G/ H7 `* s6 y
}. j: g+ z6 X7 D& a6 U

: p& S( r9 k2 }$ K% z. d7 e7 B3 x
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");3 q7 }& Q8 \4 U: f& w$ p# ?. n% X
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
3 f% [1 Z' w1 y: b+ \2 q
MODULE_LICENSE("GPL");
$ Q( n+ a- N4 S# k2 s, E, w" M" T
MODULE_VERSION(DRV_VERSION);; Q' n+ }* y0 q- A: v
* L0 h! ^: M0 y
module_init(pcf8563_init);
3 [$ `2 s! t( A5 c# {
module_exit(pcf8563_exit);

7 H) o. ]+ Y: w2 s5 r2 s

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-9-24 02:33 , Processed in 0.156250 second(s), 26 queries , Gzip On.

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

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

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