pcf85163
ordering information
Ordering information | Package | Description | Version | Marking code |
PCF85163T/1 | SO8 | ① | SOT96-1 | PF85163 |
PCF85163TS/1 | TSSOP8 | ② | SOT505-1 | 85163 |
①plastic small outline package; 8 leads;body width 3.9 mm
②plastic thin shrink small outline package;8 leads; body width 3 mm
register
HYM8563 vs PCF85163
reg | HYM8563 | PCF85163 |
0x00 | CTL1 | |
0x01 | CTL2 | |
0x02 | SEC | |
0x03 | MIN | |
0x04 | HOUR | |
0x05 | DAY | |
0x06 | WEEKDAY | |
0x07 | MONTH | |
0x08 | YEAR | |
0x09 | ALM_MIN | |
0x0a | ALM_HOUR | |
0x0b | ALM_DAY | |
0x0c | ALM_WEEK | |
0x0d | CLKOUT | |
0x0e | TMR_CTL | |
0x0f | TMR_CNT |
detail
Bit positions labeled as x are not relevant. Bit positions labeled with N should always be written with logic 0; if read, they couldbe either logic 0 or logic 1.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
TEST | N | STOP | N | TESTC | N | N | N |
N | N | N | TI_TP | AF | TF | AIE | TIE |
VL | |||||||
x | |||||||
x | x | ||||||
x | x | ||||||
x | x | x | x | x | |||
CENTURY | x | x | |||||
AE_M | |||||||
AE_H | x | ||||||
AE_D | x | ||||||
AE_W | x | x | x | x | |||
FE | x | x | x | x | x | ||
TE | x | x | x | x | x | ||
clkout_ops
clkout_ops | function | ||
pcf8563_clkout_prepare | pcf8563_clkout_control | R | W |
pcf8563_clkout_unprepare | pcf8563_clkout_control | R | W |
pcf8563_clkout_is_prepared | R | ||
pcf8563_clkout_recalc_rate | R | ||
pcf8563_clkout_round_rate | |||
pcf8563_clkout_set_rate | R | W |
问题
佰维BWMECX32H2A-08Gb停产,内存颗粒换成BWMZFX32H2A-8G-X,linux内核启动时间与之前的内存颗粒比提前100ms左右,rtc芯片驱动访问i2c1与MTK sensor hub协处理器访问i2c1冲突导致i2c读写失败,最终probe失败,rtc设备不存在,厂测失败,厂线停产。rtc驱动初始化时增加100毫秒延时可以避开冲突。
日志
异常
<3>[ 0.523511] (2)[1:swapper/0]rtc-pcf8563 1-0051: pcf8563_read_block_data: read error
<3>[ 0.523516] (2)[1:swapper/0]rtc-pcf8563 1-0051: pcf8563_probe: read error
996 : preloader
813 : lk
<3>[ 0.520859] (3)[1:swapper/0]rtc-pcf8563 1-0051: pcf8563_write_block_data: err=-121 addr=0e, data=03
<3>[ 0.520867] (3)[1:swapper/0]rtc-pcf8563 1-0051: pcf8563_probe: write error
<4>[ 0.520892] (3)[1:swapper/0]rtc-pcf8563: probe of 1-0051 failed with error -5
<3>[ 0.524627] (3)[1:swapper/0]rtc-pcf8563 1-0051: low voltage detected, date/time is not reliable.
<6>[ 0.524737] (3)[1:swapper/0]rtc-pcf8563 1-0051: rtc core: registered rtc-pcf8563 as rtc1
<3>[ 0.525180] (3)[1:swapper/0]rtc-pcf8563 1-0051: pcf8563_write_block_data: err=-121 addr=0d, data=00
<6>[ 0.739091] (3)[1:swapper/0]rtc-pcf8563 1-0051: setting system clock to 2009-01-01 00:01:11 UTC (1230768071)
正常
991 : preloader
977 : lk
<6>[ 0.574644] (2)[1:swapper/0]rtc-pcf8563 1-0051: rtc core: registered rtc-pcf8563 as rtc1
<6>[ 0.782513] (3)[1:swapper/0]rtc-pcf8563 1-0051: setting system clock to 2009-01-01 23:38:17 UTC (1230853097)
0121 i2c1 rtc-pcf8563
设备上电3.18秒左右访问0xee,9次,1ms后2个9次,3ms后访问0x18,3个9次。对应的kernel时间0.841042左右。lk里boot_linux_fdt不启动linux kernel,不会有0xee 0x18访问。
delayed work
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -650,7 +650,39 @@ static struct i2c_driver pcf8563_driver = {
.id_table = pcf8563_id,
};
+#ifdef MODULE
module_i2c_driver(pcf8563_driver);
+#else
+static struct delayed_work rtc_init_work;
+
+static void rtc_init_work_callback(struct work_struct *work)
+{
+ i2c_add_driver(&pcf8563_driver);
+ return;
+}
+
+static int __init pcf8563_init(void)
+{
+ int rval = 0;
+
+ INIT_DELAYED_WORK(&rtc_init_work, rtc_init_work_callback);
+ rval = schedule_delayed_work(&rtc_init_work, HZ * 2);
+ if (rval < 0) {
+ pr_info("pcf8563 init fail %d\n", rval);
+ }
+
+ return rval;
+}
+
+static void __exit pcf8563_exit(void)
+{
+ i2c_del_driver(&pcf8563_driver);
+ return;
+}
+
+module_init(pcf8563_init)
+module_exit(pcf8563_exit)
+#endif
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
dts
--- a/arch/arm/boot/dts/ac8257_demo_1g_32.dts
+++ b/arch/arm/boot/dts/ac8257_demo_1g_32.dts
@@ -993,7 +993,7 @@
compatible = "autochips,lcm_bridge_ic";
reg = <0x0c>;
lcm_id = <0>;
- status = "okay";
+ status = "disabled";
};
};
@@ -1007,7 +1007,7 @@
compatible = "autochips,lcm_bridge_ic";
reg = <0x0c>;
lcm_id = <1>;
- status = "okay";
+ status = "disabled";
};
/* 720P demo board */
@@ -1038,7 +1038,7 @@
interrupt-parent = <&pio>;
interrupts = <12 IRQ_TYPE_EDGE_FALLING 12 0>;
- status = "okay";
+ status = "disabled";
};
/* 720P Main */
delay 100ms
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/err.h>
+#include <linux/delay.h>
#define PCF8563_REG_ST1 0x00 /* status */
#define PCF8563_REG_ST2 0x01
@@ -650,7 +651,31 @@ static struct i2c_driver pcf8563_driver = {
.id_table = pcf8563_id,
};
+#ifdef MODULE
module_i2c_driver(pcf8563_driver);
+#else
+static int __init pcf8563_init(void)
+{
+ int rval = 0;
+
+ msleep(100);
+ rval = i2c_add_driver(&pcf8563_driver);
+ if (rval < 0) {
+ pr_info("pcf8563 init fail %d\n", rval);
+ }
+
+ return rval;
+}
+
+static void __exit pcf8563_exit(void)
+{
+ i2c_del_driver(&pcf8563_driver);
+ return;
+}
+
+module_init(pcf8563_init)
+module_exit(pcf8563_exit)
+#endif
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
0122 debug
i2c1接pcf8563(写地址0xa2,读地址0xa3),2ms后访问0xee,9次,1ms后2个9次,3ms后访问0x18,3个9次。
kernel设备树中禁用pcf8563,示波器已经量不到pcf8563驱动的i2c操作;在此基础上,把i2c1上的rtc芯片pcf8563断开,示波器抓到的i2c信号变成,访问0xa2 3个9次,访问0xee 3个9次,访问0x18 3个9次。
dts
--- a/arch/arm/boot/dts/ac8257_demo_1g_32.dts
+++ b/arch/arm/boot/dts/ac8257_demo_1g_32.dts
@@ -1106,7 +1106,7 @@
};
rtc: pcf8563@51 {
- status = "okay";
+ status = "disabled";
compatible = "nxp,pcf8563";
reg = <0x51>;
};
i2c-mtk.c
--- a/drivers/i2c/busses/i2c-mtk.c
+++ b/drivers/i2c/busses/i2c-mtk.c
@@ -1428,6 +1428,9 @@ static int mt_i2c_transfer(struct i2c_adapter *adap,
int ret;
struct mt_i2c *i2c = i2c_get_adapdata(adap);
+ if (1 == i2c->adap.nr) {
+ pr_info("zzz i2c bus %d, client 0x%02x\n", i2c->adap.nr, msgs->addr);
+ }
if (i2c->multiplexing) {
/* Once AP use i2c to transfer, It means bus belong AP.*/
i2c->multiplexing = 0;
rtc-pcf8563.c
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -13,6 +13,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#define DEBUG
#include <linux/clk-provider.h>
#include <linux/i2c.h>
@@ -245,6 +246,8 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+ dump_stack();
+
return 0;
}
@@ -357,6 +360,7 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
tm->time.tm_hour, tm->time.tm_mday, tm->time.tm_wday,
tm->enabled, tm->pending);
+ dump_stack();
return 0;
}
main.c
--- a/init/main.c
+++ b/init/main.c
@@ -979,6 +979,7 @@ static int __ref kernel_init(void *unused)
{
int ret;
+ msleep(5000);
kernel_init_freeable();
/* need to finish all async __init code before freeing the memory */
async_synchronize_full();
0123 /proc/interrupts
proc.c
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -441,6 +441,12 @@ int show_interrupts(struct seq_file *p, void *v)
int i = *(loff_t *) v, j;
struct irqaction *action;
struct irq_desc *desc;
+ const char *trigger_type_sz[IRQ_TYPE_PROBE] = {
+ "", "rising", "falling", "both",
+ "high", "", "", "",
+ "low", "", "", "",
+ "high|low", "", "", "",
+ };
if (i > ACTUAL_NR_IRQS)
return 0;
@@ -489,6 +495,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, " %*d", prec, (int) desc->irq_data.hwirq);
#ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL
seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge");
+ seq_printf(p, "(%-8s)", trigger_type_sz[irqd_get_trigger_type(&desc->irq_data)]);
#endif
if (desc->name)
seq_printf(p, "-%-8s", desc->name);
0213 MTK TINYSYS SCP
defconfig中禁用SCP后,i2c总线上不再有写地址0xee 0x18的访问。
defconfg
-CONFIG_MTK_TINYSYS_SCP_SUPPORT=y
+CONFIG_MTK_TINYSYS_SCP_SUPPORT=n
0214 i2c1
禁用SCP后i2c总线上只有rtc芯片相关的数据访问,示波器解码出来的i2c数据,与rtc-pcf8563驱动代码一致。
i2c1数据分析
function | i2c | |
pcf8563_probe | a2 0e 03 | Set timer to lowest frequency to save power |
pcf8563_get_alarm_mode | a2 01 A3 00 | |
pcf8563_rtc_read_time | a2 00 a3 08 00 38 08 02 14 3d 22 25 | __rtc_read_alarm |
pcf8563_rtc_read_alarm | a2 09 a3 80 81 80 | __rtc_read_alarm |
pcf8563_get_alarm_mode | a2 01 a3 00 | |
pcf8563_rtc_read_time | a2 00 a3 08 00 38 08 02 14 3d 22 25 | __rtc_read_alarm |
pcf8563_rtc_read_time | a2 00 a3 08 00 38 08 02 14 3d 22 25 | rtc_initialize_alarm |
pcf8563_clkout_register_clk | a2 0d 00 | disable the clkout output |
a2 0d a3 38 | pcf8563_clkout_recalc_rate | |
200ms | ||
pcf8563_rtc_read_time | a2 00 a3 08 00 38 08 02 14 3d 22 25 | rtc_hctosys |
usleep
可能出现返回值小于0,实际休眠时间可能比想要的时间短的情况,接触到的大部分人没有判断函数返回值、man命令查看帮助的习惯,量产后程序时不时出现莫名其妙的情况。
bionic/libc/upstream-freebsd/lib/libc/gen/usleep.c
sleep
bionic/libc/upstream-freebsd/lib/libc/gen/sleep.c
43 unsigned int
44 __sleep(unsigned int seconds)
45 {
46 struct timespec time_to_sleep;
47 struct timespec time_remaining;
48
49 /*
50 * Avoid overflow when `seconds' is huge. This assumes that
51 * the maximum value for a time_t is >= INT_MAX.
52 */
53 if (seconds > INT_MAX)
54 return (seconds - INT_MAX + __sleep(INT_MAX));
55
56 time_to_sleep.tv_sec = seconds;
57 time_to_sleep.tv_nsec = 0;
58 if (_nanosleep(&time_to_sleep, &time_remaining) != -1)
59 return (0);
60 if (errno != EINTR)
61 return (seconds); /* best guess */
62 return (time_remaining.tv_sec +
63 (time_remaining.tv_nsec != 0)); /* round up */
64 }
65
66 __weak_reference(__sleep, sleep);
67 __weak_reference(__sleep, _sleep);
nanosleep
kernel/time/hrtimer.c
1666 SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
1667 struct timespec __user *, rmtp)
1668 {
1669 struct timespec tu;
1670
1671 if (copy_from_user(&tu, rqtp, sizeof(tu)))
1672 return -EFAULT;
1673
1674 if (!timespec_valid(&tu))
1675 return -EINVAL;
1676
1677 return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
1678 }