找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

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

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

[复制链接]

11

主题

12

帖子

145

积分

二级会员(20)

Rank: 2Rank: 2

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

EDA365欢迎您!

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

x
# `! n; P' C9 D, J
开发板:
各位版主、工程师们你们好:
      请教你们一些问题:
             1)在内核中配置pcf8563时钟芯片启动完成,内核启动后 /dev/rtc/ 中没有pcf8563芯片对应的 rtc 节点;
             2)内核启动过程中打印 drivers/rtc/hctosys.c: unable to open rtc device (rtc0);
             3)pcf8563芯片驱动程序的 pcf8563_probe()在整个启动过程中没有被执行;
             4)请问这是怎么回事?该怎么修改???
             5)驱动程序代码如下:
驱动代码:
& z. N% x2 p: y4 \3 X
#include <linux/i2c.h>
* v) A7 g- V! ?2 i
#include <linux/bcd.h>
' T  @7 q! T0 Z0 S2 m, r$ ]" v# s; f, v# t
#include <linux/rtc.h>
% g- o' T5 u! A1 ~! L  }
#include <linux/slab.h>; I" H& K$ K" R' U1 Q$ X9 y
8 x- K( V+ n* k# C
#define DRV_VERSION "0.4.3"
9 `1 L, {* F' `5 P& ?: i

. y$ [* v( _6 [
#define PCF8563_REG_ST1                0x00 /* status *// l) k* G, @" L; C9 e% U0 y
#define PCF8563_REG_ST2                0x01
# ~4 O0 B* S- G2 Z  l
* n5 U( O9 Z2 i, Y* S. h  B2 h7 Z
#define PCF8563_REG_SC                0x02 /* datetime */
0 i* X1 E2 Y5 Y! \1 o
#define PCF8563_REG_MN                0x037 @  h) k5 \% v- ]3 A/ l0 a
#define PCF8563_REG_HR                0x042 M# a1 p7 @" u5 o4 ^) h0 F: F
#define PCF8563_REG_DM                0x05/ b( g( h$ X6 w+ [
#define PCF8563_REG_DW                0x06
3 X5 _- G4 n+ m
#define PCF8563_REG_MO                0x07; J3 u, U6 f* ?0 p
#define PCF8563_REG_YR                0x08
/ q3 U+ R- a, {' z  L

! X, R5 l4 M! t* c( [3 O+ k& }
#define PCF8563_REG_AMN                0x09 /* alarm */
: e$ B. A/ i. E: d/ c2 s: b
#define PCF8563_REG_AHR                0x0A
* O3 h7 h) o: ]5 z! l7 y' d
#define PCF8563_REG_ADM                0x0B
# h6 t/ d# d$ K; z6 y$ Q* Y+ [% W
#define PCF8563_REG_ADW                0x0C
1 O* ]( J. x2 F" S2 b( I, `

1 P% Q2 x% \/ s7 J
#define PCF8563_REG_CLKO        0x0D /* clock out */
% D5 `5 @" `  _% e- ?  F
#define PCF8563_REG_TMRC        0x0E /* timer control */" Z/ E! `3 g3 x1 p
#define PCF8563_REG_TMR                0x0F /* timer */
: ^1 Q% J1 b# }' |# N
. P; l, Y8 Z. S2 W, E
#define PCF8563_SC_LV                0x80 /* low voltage */5 ]. n6 W3 c7 ^
#define PCF8563_MO_C                0x80 /* century */' \1 W$ e( ?4 k8 J
1 u/ ]) g! l4 T3 U  U# _5 b
static struct i2c_driver pcf8563_driver;
' |. z  ]5 p9 D$ k. i( J

, Q( |! t2 c2 _4 o) B( l& t0 |
struct pcf8563 {, Y! f" o! c5 D3 u8 C
        struct rtc_device *rtc;
( `, u4 x: L6 {
        /*
; W4 S( Z/ p' N. [! u
         * The meaning of MO_C bit varies by the chip type.
3 D6 ~; V3 b9 P8 L2 B5 e
         * From PCF8563 datasheet: this bit is toggled when the years1 `+ L6 l: ^7 I0 J: t* H
         * register overflows from 99 to 00* G' |& ?; h! h1 J+ V) k0 `7 U
         *   0 indicates the century is 20xx0 X" A( Z0 H1 g, z) n# k8 l" h
         *   1 indicates the century is 19xx
- {! S; C# W/ k) A( G) w
         * From RTC8564 datasheet: this bit indicates change of$ Y- \. e' [1 ^) U* I$ n
         * century. When the year digit data overflows from 99 to 00,
8 z( T( V2 q. q9 n" l! I3 P* J" L! {6 g
         * this bit is set. By presetting it to 0 while still in the
  Q* A7 L4 |( D7 m, u
         * 20th century, it will be set in year 2000, ...
7 ~6 w- f: n2 `9 [' g
         * There seems no reliable way to know how the system use this) j7 ^; A1 ]' [
         * bit.  So let's do it heuristically, assuming we are live in5 E3 V' ^7 k/ ^
         * 1970...2069.
5 W7 t% M5 y3 ]/ B! R0 t
         */
! E) [' c. O& J0 A; w
        int c_polarity;        /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */  x0 J* u0 i. J: E9 T# d- t
};
: q( D# [3 e0 n( e

) B3 N* E( h2 n7 r) t
/*! W: ^2 j2 s* P, ]; V# j1 l6 g
* In the routines that deal directly with the pcf8563 hardware, we use  G% A, V/ S0 m
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
& y0 z' i* `0 x0 _5 x
*/0 r- s6 J7 S$ D' O8 K
static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
3 E8 F* e% h; O- \
{
6 j1 D& ?- y# z+ X2 D! s
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);6 Y: n% j# T/ A
        unsigned char buf[13] = { PCF8563_REG_ST1 };5 G, i$ {9 k! n  s) r
5 D. O" r+ Z3 N" n7 `+ a; K
        struct i2c_msg msgs[] = {3 `2 a, \% ^" _
                { client->addr, 0, 1, buf },        /* setup read ptr */0 c3 C1 D( k& A. l8 \: ~5 U$ U7 X
                { client->addr, I2C_M_RD, 13, buf },        /* read status + date */2 C7 {3 j) s1 g' `3 _6 g8 z0 Z
        };' w$ G0 }9 D7 b, e& x
0 u/ h# h5 z  ?6 S, u2 E# L
        /* read registers */! y/ J; X0 x8 L$ \4 w2 d
        if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {! Q! v, u* B4 G7 y- a
                dev_err(&client->dev, "%s: read error\n", __func__);9 j% r' L' H, z
                return -EIO;+ S$ r- C; r% U
        }8 R9 B5 q4 h3 o* D8 E4 l  H" p0 p
; B1 R' p$ U, j% V4 r
        if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)0 H/ N' \* M/ q# d% R* Z3 d
                dev_info(&client->dev,
. i+ W. q6 c' W* ?  f! b
                        "low voltage detected, date/time is not reliable.\n");7 J5 }8 v: I! t! K1 Q/ V
+ `8 ~, l0 q8 \
        dev_dbg(&client->dev,# R$ _1 Z4 {' \/ O6 I8 Q1 C* z. ^6 O
                "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
+ i0 U. _5 S7 D% X6 s
                "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",* R4 T0 |8 _8 E3 a" _
                __func__,/ l8 I# h9 l5 J. Y% A, c; W
                buf[0], buf[1], buf[2], buf[3],
6 X! @# k3 C5 H8 c6 S& {
                buf[4], buf[5], buf[6], buf[7],- R8 I) `& c* U+ T! e% Y& q; w2 ~. L
                buf[8]);
* h' C6 o& F# n. V
/ Y: P# l. o7 S. l- L
' h  U0 Y; _) l1 b4 C
        tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
0 W; ~7 Z$ F8 |& {  U' N- t
        tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
: g  m7 J: V# A
        tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
2 K# @9 G! W8 c
        tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
, W. w8 V/ r# J
        tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
# y4 n( n* ]( X
        tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
6 s5 e# ]8 N" R# s) E
        tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);* l2 h/ ~/ Z% z* N
        if (tm->tm_year < 70)7 V2 @5 N6 @1 u  G
                tm->tm_year += 100;        /* assume we are in 1970...2069 */+ s; g- T2 U* Q$ F! O
        /* detect the polarity heuristically. see note above. */
% a4 G! k( K7 f" O$ Y' j9 A
        pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
  w: r. x; @) {2 C; f) v
                (tm->tm_year >= 100) : (tm->tm_year < 100);
9 o: S! W2 J' K) @) Z1 o0 `7 N  d8 A
9 d  Y) M4 n$ H& l2 h. y
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "$ l: o0 Y+ d. c) w4 D! O6 T: z$ J
                "mday=%d, mon=%d, year=%d, wday=%d\n",
" Y- `7 R6 E# l
                __func__,8 m( m! ^8 k/ O8 u) S& H6 V
                tm->tm_sec, tm->tm_min, tm->tm_hour,
$ G8 J0 }- S9 Z1 T
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
! S- v( Z3 Y* L' p' X- }

/ |3 {% x/ h5 E& M% s, S$ f
        /* the clock can give out invalid datetime, but we cannot return. \! s3 Y# y5 R2 q* d" u
         * -EINVAL otherwise hwclock will refuse to set the time on bootup.! K8 _2 r! `2 g3 @- M/ m  N
         */
2 O5 O; m- a9 ?- b+ }2 E1 Y
        if (rtc_valid_tm(tm) < 0), j. C/ v* \& f; \5 j1 z
                dev_err(&client->dev, "retrieved date/time is not valid.\n");: a) @& i, E* h/ \& t
- g2 t! J* \0 q& F' o9 z
        return 0;1 c5 G' w: p* x8 K# q
}8 K( s  h9 |& I; c2 Y5 @: H( @9 u; p
; z% N" }8 ]8 b6 M
static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
- a& n0 K  z, t$ _* D* ]% n! I7 E  u
{( w5 Q- D7 s, W; n! s7 t4 R3 a
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);* f# Z3 n+ k8 l' p
        int i, err;% A/ n6 O, u3 V+ Y+ R" K" v
        unsigned char buf[9];% ~7 j$ _& n0 {: }) |  q/ y& D

5 g" O+ |+ y0 W) ~: o- ?! }
        dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
( i- f5 N. t1 y1 s- i3 O
                "mday=%d, mon=%d, year=%d, wday=%d\n",3 k; `: d# g9 h4 }
                __func__,
! h) ^9 M7 K- u+ C
                tm->tm_sec, tm->tm_min, tm->tm_hour,5 `! o8 ?  H1 _! m7 Q5 U
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
* c" I! T9 y3 q5 c! r8 H

; y, u! B7 e/ S# v; ^, U: G
        /* hours, minutes and seconds */
7 h/ T. h1 I2 d( T" M6 C
        buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);# j5 z( H% y4 I, _) }6 h# U) @
        buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
% [7 }& I. ^7 H6 [
        buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);
9 U8 U* Q. Q; F: {7 |7 V
# O' {8 A7 Y+ s2 A
        buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
) @5 D' N6 W, O( C" O; }
9 U, A4 F, E; \- ^% I+ ]5 A
        /* month, 1 - 12 */
3 F0 s, ]) w1 I- t+ d$ V9 ^! O/ K7 R
        buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);* F$ ^/ }& j" g' ]5 D; T! D  V

- E5 {/ r- N2 \8 C, j7 ?
        /* year and century */  e5 r. m( X  I& [; \
        buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
& _5 G/ l# n9 r: g
        if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
& n$ A9 R- B/ G0 k  b! p3 r6 T# V
                buf[PCF8563_REG_MO] |= PCF8563_MO_C;( L4 Q0 A+ M2 ^4 D; x
. f% o/ V/ A+ q7 M) u/ k" X( V
        buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
4 |9 S4 r/ P$ v5 ]" k
4 V, F, j4 N; Z7 P
        /* write register's data */
2 P" a* S: i( G( D* m: L; B2 r
        for (i = 0; i < 7; i++) {( M* e9 r$ \0 O4 V: y+ k
                unsigned char data[2] = { PCF8563_REG_SC + i,
) f) G3 e* p' k( l
                                                buf[PCF8563_REG_SC + i] };6 ^7 f; Q; P, y5 i& F
& n% t- ~  ]0 B# \: ~+ T) {
                err = i2c_master_send(client, data, sizeof(data));
5 ?4 k6 f& u$ i1 k/ e
                if (err != sizeof(data)) {
( x& q8 U8 M! i+ h3 R5 R9 T
                        dev_err(&client->dev,8 L0 O# ]. Y. Z& M4 r* A' j  B
                                "%s: err=%d addr=%02x, data=%02x\n",
6 F9 ?2 a# P' J( Y1 D
                                __func__, err, data[0], data[1]);
- ~, g1 i( ~0 D
                        return -EIO;3 D$ J4 N6 e/ {0 V2 ^( ^/ X
                }$ @# U! {/ x* d# F5 f3 f( K
        };0 x* [0 Q  V) A2 q/ ?; S

0 X+ a5 N% P6 _# b% O2 |) R
        return 0;  d, U% f0 u7 V6 V+ c1 o/ I
}- [% c8 u7 R3 `2 q+ n

' ~1 u* W5 j8 o) J) |5 F" d/ M" s
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
- v8 s; W4 c& F. e6 F
{
  f, n" y. T2 O
        return pcf8563_get_datetime(to_i2c_client(dev), tm);% J2 X5 l2 ?) Z
}/ t1 _+ p0 {8 v/ R7 Z- f1 r1 q

% H2 Z' a! Y( }9 E& M
static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
! F3 b3 c2 ^  k* ?
{4 B% d1 Z" A0 L( v: ]/ ]! H
        return pcf8563_set_datetime(to_i2c_client(dev), tm);
3 R5 e: w9 Q' k* e0 B: R) r) {8 i
}
, _- N$ t% h. |& e* W

5 ^6 `' Q% r3 c7 O- {: z) \! O
static const struct rtc_class_ops pcf8563_rtc_ops = {
% w0 j& [: j6 [
        .read_time        = pcf8563_rtc_read_time,7 I& D2 i( `" ?) ?
        .set_time        = pcf8563_rtc_set_time,, M7 X, t% t+ U$ c0 v) i7 }9 Y
};& l8 a3 g7 X" n9 {: W

- F6 L1 Q& o5 a! q3 R
static int pcf8563_probe(struct i2c_client *client,
- V5 _0 b, F+ _4 D: \; I+ V
                                const struct i2c_device_id *id)
2 u6 L8 m9 I4 ~8 z: p
{
6 x4 G' K" ?. a; f& @
        struct pcf8563 *pcf8563;( j1 G& q  I: R  L8 W+ y2 r

6 j+ X  }( G3 ^0 s! C, L
        int err = 0;' n/ J& O3 D* @

7 d3 W4 V$ D/ I( X6 L" m, Q
        dev_dbg(&client->dev, "%s\n", __func__);
- N" \2 V% M% P: T7 X
7 d/ h, |" N/ x) `( X4 G
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)); q5 ^# e6 O" M, ^/ n8 E1 Z
                return -ENODEV;
" a4 w/ S+ J0 f- W% |
" p0 W3 L1 A! e
        pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL);' V( D  U( _0 n
        if (!pcf8563)+ v4 f# }" b/ D5 K. |$ O/ Q. k
                return -ENOMEM;' J& {; [" ~2 }- ]4 {

& @  q' t. @3 R/ O7 p1 s. B7 c
        dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");+ T, l2 n; F2 p' u- B0 k0 D  Q

3 P2 C  y, g$ ~, Z6 J) T3 a* A
        i2c_set_clientdata(client, pcf8563);8 m  c+ l) X% r

0 b9 W4 @& t% [1 x4 E% ~2 J; l3 t3 ^
        pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
, R7 W1 H. T4 j8 I6 m/ M8 \
                                &client->dev, &pcf8563_rtc_ops, THIS_MODULE);
7 ^8 T& A  G2 \* u8 X4 i* F# q+ s
! H) A' c7 k- E, O& ^
        if (IS_ERR(pcf8563->rtc)) {! M& I7 m5 I2 t/ S
                err = PTR_ERR(pcf8563->rtc);5 m0 D' y5 U) l' M" E, ~+ k
                goto exit_kfree;
0 U" Q! u; a% s
        }
. h. i' R( f2 W

( A+ g: \/ E" V- @4 k; ]
        return 0;
" h  A) v8 T8 t5 @7 C! @" i" t' f

" v+ G9 O. m. l+ b2 }
exit_kfree:) c1 A8 @; @( W9 J" l
        kfree(pcf8563);
5 K2 J* ]$ q3 d: d% T/ N( E. ?

* p, H/ \  H& K9 D! H
        return err;& s  v; z+ D- U& T$ T7 V
}
; m" p1 X. S4 C  a6 ]- H3 ~1 t

  m% [# j3 A9 @2 m$ E* Y
static int pcf8563_remove(struct i2c_client *client)8 {4 f6 H, V9 G5 [- t" p
{
. [9 T- \) B3 [4 M( k& ~6 A
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
( G3 ~0 u+ y7 O
9 x) {7 v: K' @; m( X9 t
        if (pcf8563->rtc)3 S4 ], Z+ n$ B- _4 R
                rtc_device_unregister(pcf8563->rtc);* u# [# a# a& B/ m

2 L1 _8 c% [  u! i& Q* o7 r9 a& ?
        kfree(pcf8563);- D4 t, |, e0 ?2 p

# K9 a! K& z+ U
        return 0;& E6 n: [- P, I
}! W, g. v+ I) K& b; o0 W, E
7 R$ _( R" b) G1 d0 u
static const struct i2c_device_id pcf8563_id[] = {$ v3 F& [+ z) h3 L) u8 q7 A
        { "pcf8563", 0 },
- _& ?7 M6 U# f" g& ~) ]! T7 a
        { "rtc8564", 0 },
5 b5 C, W' Q# t4 Q- I
        { }
# e+ ?  h0 N8 P  O( o/ T
};
; q- z; X! D: [& ]1 y. k  }0 E
MODULE_DEVICE_TABLE(i2c, pcf8563_id);' O8 n8 M7 V6 Y
; p0 s3 s# d5 l  y+ Q* K( U* B
static struct i2c_driver pcf8563_driver = {, W8 K9 b5 q; c8 P( G% y
        .driver                = {% c! Q; h$ e2 b8 ^5 r8 u
                .name        = "rtc-pcf8563",  c. h8 i( k, p
        },0 g. Q0 A7 B1 M* Q4 D5 D* w
        .probe                = pcf8563_probe,
( {; V& H6 |0 ~5 G* }
        .remove                = pcf8563_remove,
' D) R- n' b/ f2 c. h( @
        .id_table        = pcf8563_id,- p, X% `5 [0 x8 @+ ?7 u+ M& Y
};3 h2 {2 `- j9 M* W( [8 o

$ ~8 ~3 ~/ a( p5 o& N% C' B
static int __init pcf8563_init(void)1 F7 O4 |- m5 ~+ S5 O
{% N/ ]5 E8 D1 K
        return i2c_add_driver(&pcf8563_driver);( p# B% i2 E) ^2 G$ P9 t
}0 t7 F1 y% R" {7 X; C

+ o& v% M% q% R
static void __exit pcf8563_exit(void), b/ h+ r. L; o. v; ^% f1 {9 d
{
$ O% F1 n5 Y$ O% y$ v; z' y9 j+ L
        i2c_del_driver(&pcf8563_driver);& |# I& [" t5 ~) _# x* A! H
}
( b7 B2 _, z2 |+ A9 v+ M3 U
# R+ d' |" y9 f' X# F
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");: q' S: s9 m" H/ D/ [
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");  E4 Q- N' g4 G$ [) Q6 W
MODULE_LICENSE("GPL");
! n7 x4 e* @! z3 m8 \
MODULE_VERSION(DRV_VERSION);1 c/ y1 X1 k8 O% g

+ U% ?/ k$ x8 b$ K0 v$ E
module_init(pcf8563_init);
- p* t/ v: E5 `1 ~/ `# G
module_exit(pcf8563_exit);

4 Y6 p2 z( x9 |* ?  `' {3 [
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 支持!支持! 反对!反对!

3

主题

135

帖子

2203

积分

四级会员(40)

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

积分
2203
3#
发表于 2017-11-25 20:27 | 只看该作者
哪个正常的人能崇拜一只蟑螂呢?

0

主题

7

帖子

36

积分

二级会员(20)

Rank: 2Rank: 2

积分
36
2#
发表于 2017-11-24 10:47 | 只看该作者
这么一堆,看蒙了,不过还是了解一下下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

巢课

技术风云榜

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

GMT+8, 2024-11-8 22:19 , Processed in 0.067500 second(s), 35 queries , Gzip On.

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

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

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