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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
9 }5 {; y  a+ w( a4 W8 T
开发板:
各位版主、工程师们你们好:
      请教你们一些问题:
             1)在内核中配置pcf8563时钟芯片启动完成,内核启动后 /dev/rtc/ 中没有pcf8563芯片对应的 rtc 节点;
             2)内核启动过程中打印 drivers/rtc/hctosys.c: unable to open rtc device (rtc0);
             3)pcf8563芯片驱动程序的 pcf8563_probe()在整个启动过程中没有被执行;
             4)请问这是怎么回事?该怎么修改???
             5)驱动程序代码如下:
驱动代码:
! q8 b; j. l7 z" J# h9 K
#include <linux/i2c.h>
  v1 W4 e1 R" w% D4 w9 \* x
#include <linux/bcd.h>  I* L1 }/ C. N, v* H* d
#include <linux/rtc.h>
# i; |1 q) F2 b5 s
#include <linux/slab.h>: R1 z7 h9 B. J, T

/ @7 g8 r: W- P8 u4 J: a' i3 h, }* r
#define DRV_VERSION "0.4.3"
1 a  n* T. E8 ^1 F

& X# a/ G  B' B: c+ i  ]
#define PCF8563_REG_ST1                0x00 /* status */
) F$ r+ l( ], V
#define PCF8563_REG_ST2                0x014 C. X2 E2 b# e& L& ]- E, e9 Y
/ G2 M, F3 l- l5 p. Q
#define PCF8563_REG_SC                0x02 /* datetime */- ^' x4 d4 S4 ?
#define PCF8563_REG_MN                0x03
: ^  e3 }8 v/ u9 K/ I$ k
#define PCF8563_REG_HR                0x04" E! y! U, j: S0 O! v; j  J0 _+ V
#define PCF8563_REG_DM                0x05
' C* H& X# p* m% l/ a; ?' W* B
#define PCF8563_REG_DW                0x06
( B% F9 m" s4 G' ?: r' E* f- n
#define PCF8563_REG_MO                0x07
1 T5 S- N' @6 u/ |# @, I
#define PCF8563_REG_YR                0x08
2 b: r- [  {; O* A  o
$ ~8 l) X1 y' t+ t6 N' U
#define PCF8563_REG_AMN                0x09 /* alARM */
9 ^! n, P, g0 X) S
#define PCF8563_REG_AHR                0x0A; m5 D- y/ L: j
#define PCF8563_REG_ADM                0x0B
* m/ n* l, s4 y2 P
#define PCF8563_REG_ADW                0x0C
8 k( y; `; _0 p/ N' `

( x' Q$ x3 r# S4 G; G- |1 p. I
#define PCF8563_REG_CLKO        0x0D /* clock out */
: A3 J9 E* t3 {( b! y, S! D2 U* N, S
#define PCF8563_REG_TMRC        0x0E /* timer control */
5 ^  r  F, L/ r" J
#define PCF8563_REG_TMR                0x0F /* timer */
5 k3 P2 C/ f# e0 e0 e

( n3 G4 ?* ~+ T3 l3 M& C4 B5 H/ R# v
#define PCF8563_SC_LV                0x80 /* low voltage */
: F- u! Q1 ?* l; B
#define PCF8563_MO_C                0x80 /* century */
$ f4 V2 `7 B0 @/ C& e

0 c# `" L1 J, e4 b
static struct i2c_driver pcf8563_driver;! Z! i6 O3 I* p
" h2 y! l0 ^8 X9 e7 Y" q6 h2 G$ z/ e
struct pcf8563 {8 I7 A) G6 @; D
        struct rtc_device *rtc;
+ H: X8 H! r" i2 ]$ `
        /** c+ M2 M- |6 g8 _3 ^
         * The meaning of MO_C bit varies by the chip type.
  r. G% [/ A. h4 J; n' m4 t9 j
         * From PCF8563 datasheet: this bit is toggled when the years
+ ^4 I: R; ~; ~7 {( p2 b
         * register oveRFlows from 99 to 00
) p8 h$ N4 _0 a5 C* D1 }6 }
         *   0 indicates the century is 20xx
4 ]! x0 E- K2 V0 }2 Z! N- }# ]
         *   1 indicates the century is 19xx0 p/ D& [- k! @0 w+ z. [2 @* {2 u
         * From RTC8564 datasheet: this bit indicates change of6 ~' o  t6 y# n' c0 ~  d6 t- c
         * century. When the year digit data overflows from 99 to 00,( q) u; C  i) k
         * this bit is set. By presetting it to 0 while still in the. B* F  [' }/ e% n/ o! ^8 c
         * 20th century, it will be set in year 2000, ...
1 }+ S* |  C3 \5 B# O1 F
         * There seems no reliable way to know how the system use this5 K# \1 E! B2 c# R+ f! s" o
         * bit.  So let's do it heuristically, assuming we are live in' a& S* c! w: p6 P
         * 1970...2069.
5 u5 _. Q, b0 ]
         */
! o+ t, J3 k$ I8 Y
        int c_polarity;        /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
4 u4 U7 b1 d/ q2 f( {
};
& e  M! D1 l- W# |5 B7 H' t
+ g- e! z. q$ R2 t) ^3 S
/*4 G, f2 [  o) n9 r
* In the routines that deal directly with the pcf8563 hardware, we use
$ D7 l$ `9 [: V$ q. t
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
2 y+ ^: X& z; S# p
*/
; l4 L! T! {. G0 J; j3 F
static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
. b2 g' s+ d. B1 Q+ w" ~3 n# \
{
9 ]* W) X- s2 n4 s$ [, c
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
& W7 m; {% i# z
        unsigned char buf[13] = { PCF8563_REG_ST1 };, g$ F  ^" g: L. L
9 M  ?, O, }, \; n: i
        struct i2c_msg msgs[] = {% l1 w8 }3 j6 M
                { client->addr, 0, 1, buf },        /* setup read ptr */6 X0 x+ x* P( N6 z. Y6 u* F
                { client->addr, I2C_M_RD, 13, buf },        /* read status + date */
" K4 Y4 Z% G! }$ A0 a3 V3 c
        };
* {: W; L$ }2 _* h7 P

2 Q0 F; o- U1 |
        /* read registers */+ q* g# D5 |2 w% A& f6 g( Z- k" ^
        if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
! J. w( y) G. @% g( D8 l! c  _# h
                dev_err(&client->dev, "%s: read error\n", __func__);
  y' D2 y' f8 b3 n+ M
                return -EIO;
2 r% I: f( U, C* o+ }
        }2 O& h+ }& j# X) a' @! `- B6 t$ F
, W; d8 X/ g' c) T  a0 u: q
        if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)
5 g3 y0 d; F. v  `; }' C
                dev_info(&client->dev,. o, K% v! V% @: U, ?3 Z
                        "low voltage detected, date/time is not reliable.\n");
' M5 y- [' x# x4 H
/ r: M/ F& S4 ^; d
        dev_dbg(&client->dev,' N3 {5 ^7 O. N, @+ V7 T
                "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
2 X* |3 U3 R, ?* z& q: ~( p( H$ a  I
                "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
- O  a% W) T% L: m& e  T
                __func__,
8 \! @) m6 R7 c
                buf[0], buf[1], buf[2], buf[3],. w+ R2 i# A- k9 K1 u9 b( S
                buf[4], buf[5], buf[6], buf[7],
. l# n$ {3 b/ y# c4 L: x
                buf[8]);+ e# z" H  d2 x: m# |3 i) M/ t
0 a& \, T; I$ U1 N

7 w; B! t0 q) Y
        tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);9 [# U4 B" k/ B: q& j6 x- B6 F1 j
        tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
- R2 l4 T9 [- T+ h) g! L" a
        tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */+ M1 Y# n3 S- \; A8 ?( W
        tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
: s- @; t( q8 t* L& j
        tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
9 M" F$ B! b4 e, O9 y
        tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
) ~6 Q  _  r! @- L4 L
        tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
! Q( Z3 H4 [0 N5 X0 Q
        if (tm->tm_year < 70)
' h8 {; C* l6 x! o' ?2 U2 ?4 N
                tm->tm_year += 100;        /* assume we are in 1970...2069 */  f# {) k9 F- _+ w+ z/ \, @
        /* detect the polarity heuristically. see note above. */- t: k  Z* v2 V5 t! d% }
        pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?# S, r2 V+ S- K( u5 w
                (tm->tm_year >= 100) : (tm->tm_year < 100);0 O& [# w: l- C" P/ Z6 h9 y8 c: l5 k
) V3 F7 w9 [" Y" O
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, ": {* h# @& E' I# H8 L- Q7 i
                "mday=%d, mon=%d, year=%d, wday=%d\n",
7 o% t- z- A9 l4 m4 v& t
                __func__,8 e7 i/ m& ]7 E; @4 R/ m  l, w
                tm->tm_sec, tm->tm_min, tm->tm_hour,
/ B* @6 L$ o) ?1 x5 b- s  B
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
; c- j# o. ^% w6 a. r; T

) k4 \( X& F. z0 ?& F
        /* the clock can give out invalid datetime, but we cannot return/ J7 m$ M" o3 P1 d
         * -EINVAL otherwise hwclock will refuse to set the time on bootup.' k8 L( o0 M2 q; b
         */
3 Z& V8 B  z# o0 ?* I, N
        if (rtc_valid_tm(tm) < 0)
# s/ Z' p: r+ }1 N) @% @3 j- ~2 K
                dev_err(&client->dev, "retrieved date/time is not valid.\n");* w# c) Q, z; ~' }$ u  e1 \9 ?$ }
# e* g4 k; s2 N' x
        return 0;
( g1 Q3 z2 f& B$ i( z4 E
}
5 z3 S5 q( D3 ^2 z8 d+ i( {5 l/ H

% q/ T: D, p) U- |+ [$ {
static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm). W+ C+ w' ^+ J' F
{
' |& d: j' J- `1 ^0 S" @
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);4 Y5 L0 J0 K& e+ V, J) C- C$ M
        int i, err;6 V$ e$ O( d% j0 `) w1 y/ |- v
        unsigned char buf[9];
' E0 l" f7 ]/ H/ k0 h; r

( u1 I# w) q& F7 z5 O: v
        dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
: I4 }% K9 Y+ j1 t4 \. C
                "mday=%d, mon=%d, year=%d, wday=%d\n",  L+ V/ k' E& ?# u5 l
                __func__,
% Q. m9 r4 r# z" I, V- J( S
                tm->tm_sec, tm->tm_min, tm->tm_hour,
) H$ {$ O! j+ x8 x5 @; J% q/ B
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
) x$ |3 S+ f2 r4 w# |3 d  P
! P, s9 _( O* g, E! N, a, F
        /* hours, minutes and seconds */
' b6 J) V- Z% K: j2 W
        buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);
* I- e2 m/ r- y! W+ d# n1 }
        buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);) ~/ ~4 r6 l! i+ ^2 j* Z' @
        buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);; f& H- F6 Q: {+ `
4 k# \" F6 s' K7 c
        buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
' l5 f- m6 y6 S$ e+ [5 g
+ L( A! E& }! \+ A
        /* month, 1 - 12 */
' L& U5 b9 C: ]+ o, Z* x7 |; C' l
        buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);3 J$ p+ A$ j! \3 {
7 O$ x& [2 L/ d( R0 i
        /* year and century */
  I$ ^2 r' F0 k' L
        buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
: B7 @' U5 |3 \
        if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
. H9 ]* l4 K9 o! o- A% O  q3 o
                buf[PCF8563_REG_MO] |= PCF8563_MO_C;) `: F. M  x: E+ F7 O9 E

9 F0 J- s2 L0 Z  ?7 |# D( N3 @* X
        buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
2 B* D  {, s2 M) \7 h- H3 x" v# S. H
  k# Y% c1 D' a* W; e
        /* write register's data */4 X0 S3 g  Q6 \" F, a
        for (i = 0; i < 7; i++) {
- B! V$ W  f& {/ d- B
                unsigned char data[2] = { PCF8563_REG_SC + i,
6 p) n9 F4 B- @- ^& r* E
                                                buf[PCF8563_REG_SC + i] };, Z; P% L' |* o! V/ O6 p# X
, \- v, x& [- b( p: X# X
                err = i2c_master_send(client, data, sizeof(data));
0 r) h# m( ^! H5 l3 r2 Y1 q
                if (err != sizeof(data)) {6 T; |& d% k7 l0 }' S6 O
                        dev_err(&client->dev,7 P* S1 S! f( y1 h% X( l# D5 N0 @
                                "%s: err=%d addr=%02x, data=%02x\n",* u) x& K( [4 K0 p1 [
                                __func__, err, data[0], data[1]);
$ A" N! R3 Z+ d- }! W
                        return -EIO;
, ]- G( k' f  ~) Z
                }; @' w( T3 j9 J# f1 b3 V- F
        };
8 s7 q# c) K( |* `6 O! Q

3 `! O7 N4 J: ]/ O3 B# ~; H
        return 0;
& ~, \5 C% j0 Y0 s& f
}* u( M& ], G7 w. Q; d  O8 u

0 H- Y$ h  ]5 d4 e3 z& ~" S
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
0 ]( r/ S/ j/ a* K/ C2 B/ }
{
( N: u( U2 A5 N* b1 n
        return pcf8563_get_datetime(to_i2c_client(dev), tm);
# `) x0 m3 v2 I6 c
}
8 o" [4 N( G) g" F( X6 A) q5 D  E8 P

/ p3 j) D' K# i) V1 h4 Z+ B4 c
static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
& U/ e" N2 E- y0 \2 x# b% W  P
{
0 w6 L- t6 t+ M, e! n9 y
        return pcf8563_set_datetime(to_i2c_client(dev), tm);5 d( z3 d2 f. w! x2 B# j
}
' |8 `) J6 H& w4 d4 Z/ Y8 D

1 r2 p: V. T$ e/ R9 z# L
static const struct rtc_class_ops pcf8563_rtc_ops = {
7 h! O, s+ c, P+ X  X
        .read_time        = pcf8563_rtc_read_time,+ Z. v7 h4 n! n" R, x- k7 W) V4 F$ `
        .set_time        = pcf8563_rtc_set_time,
  x. e( K# `; }8 I2 |  o
};' r; e) T/ v# G* Q
6 `2 C! `  U5 J! |  o# S+ u8 r" s
static int pcf8563_probe(struct i2c_client *client,
& k* R/ e: F. W& Z& C0 T# N, {
                                const struct i2c_device_id *id)5 k% {0 V- ^0 k
{2 }; `" Z3 I# i1 T
        struct pcf8563 *pcf8563;+ {1 f; `2 B  p4 @1 d* Z

& e  L' @$ @3 ^8 ^* e8 d
        int err = 0;$ _7 r1 j8 l! {' F! H' A
3 V7 @# w6 R) ^) G, Q+ H
        dev_dbg(&client->dev, "%s\n", __func__);
0 j: H' r) G5 O2 S- m, O
0 X  G; P7 g- D
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
. F& i* b4 f; S4 }
                return -ENODEV;/ ?8 J% A3 B& U+ w, \; ~, J3 c$ Y

& f1 d+ J$ O/ e4 B' J! g' y1 y
        pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL);
! R% l) o0 s& Y
        if (!pcf8563)
8 z* D7 }7 n$ \0 B
                return -ENOMEM;
5 A! Z) f1 X5 P3 `" _/ l
2 U. y, M  {+ p! |' n: }/ q$ T. ^
        dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");0 V" t2 a6 `3 A  S" o! x

3 |5 e; c4 n$ Y% q/ P' J
        i2c_set_clientdata(client, pcf8563);7 l  j4 Y8 p( |: a7 Z; i3 G% L6 Z/ _5 q
6 x+ C8 N3 T. U$ p
        pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
( S  U. @7 |+ F
                                &client->dev, &pcf8563_rtc_ops, THIS_MODULE);
' \4 T) @! \! B7 `- M+ X" }' h1 a
/ y$ M  H5 r& c% `
        if (IS_ERR(pcf8563->rtc)) {
6 V  t) e* K. s+ l" z
                err = PTR_ERR(pcf8563->rtc);
# q: d: r' R7 H6 h$ Z7 _
                goto exit_kfree;
, r1 Q" T" T- |; P
        }
8 _( w% Y: {+ O9 ?7 d6 f) y3 c

4 q! p5 D4 {, x8 k' [& N
        return 0;
/ \0 ?! M+ l5 \8 z+ X
. a2 I' l( b( W, \
exit_kfree:
  O% {6 m; j4 b6 \
        kfree(pcf8563);
# t6 k, a1 {0 I& R' f
9 F" t% x) q. l+ O. Y- k5 L% i
        return err;* R0 m7 k  a; e' `
}- `* _7 E! m! h8 r6 w6 U$ i" E
# z4 X* l  s, }& z5 d4 T: D# t/ D
static int pcf8563_remove(struct i2c_client *client)( L' W1 B4 @/ g, ?+ _* V
{
; Z8 @2 ?9 P! A
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);! A5 F) F5 N  ^* T0 Z

- U% [7 k9 W' [/ p3 P9 T$ M
        if (pcf8563->rtc)
. h: \' P# F$ t: B
                rtc_device_unregister(pcf8563->rtc);7 O- v) |  I1 A5 w
; V8 d: N0 ^9 R
        kfree(pcf8563);
- v) X5 \1 I+ y+ Z8 P

4 I! k) R& N) L: q4 t2 H' {
        return 0;
1 c7 Z3 v9 l4 e7 K/ a  p
}* n5 k4 C! x3 z3 P! B

  n. ^' @2 ]: |
static const struct i2c_device_id pcf8563_id[] = {
+ S8 o+ A, `% v1 I
        { "pcf8563", 0 },
- o: T$ n+ H$ Z- {% Y$ W! a( U
        { "rtc8564", 0 },
7 ^# j! T3 y& \2 E
        { }) V8 ]* _' |" k& r( P
};
* s( X7 p* p" ~7 |; M# n8 D
MODULE_DEVICE_TABLE(i2c, pcf8563_id);( h# b  P0 R7 l1 i2 X4 s0 d
' X* k6 f8 u$ O- J  n
static struct i2c_driver pcf8563_driver = {2 a8 `. x3 Y6 T( O' n  p* @
        .driver                = {4 m  W: ^& Y" o
                .name        = "rtc-pcf8563",
) h- r* N4 s( P- E
        },
* d' c; u( d' M0 Z, o0 c3 y2 f
        .probe                = pcf8563_probe,
' C3 N4 p/ u8 g* K7 b; ]
        .remove                = pcf8563_remove,
# i! u. w: z  ~+ d' \$ n# q
        .id_table        = pcf8563_id,
; l1 d! a  R/ Z5 k8 o
};! g% C( Q& }6 G7 \" K5 S

0 N( c* n/ m+ X
static int __init pcf8563_init(void)
% q+ P% N, R; E# S7 a% \6 m( n
{
% i5 n# G  v1 j
        return i2c_add_driver(&pcf8563_driver);
2 K3 `' E4 {9 Y5 [# O2 `* _
}
7 k+ @- q4 n7 W
( p  l! D7 Z; o- V6 P. z
static void __exit pcf8563_exit(void)9 }+ k, m7 A5 a) `
{
: t, j' g4 M; g' b( v( Q: v' u# N6 I
        i2c_del_driver(&pcf8563_driver);9 A4 |5 }) P4 P3 a
}
0 n/ n9 _) {& a- D# q2 V

' N. V6 Z  s! k
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");( y( x& ~6 Z& @+ j; m
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
. E7 e5 ]2 c" V4 K7 F
MODULE_LICENSE("GPL");) G6 a$ F- ]! t( z4 ]% V
MODULE_VERSION(DRV_VERSION);
% ]8 V6 T  Y$ q
. q* I7 g1 o" o
module_init(pcf8563_init);
6 d! l& l: s- z8 \4 K
module_exit(pcf8563_exit);

1 d2 C3 E& H! z$ o0 I* {) K2 S2 q# S# ^

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-8-20 06:07 , Processed in 0.140625 second(s), 26 queries , Gzip On.

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

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

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