hym8563/pcf8563 定时关机后,中断没有清除,导致INT脚一直为低,系统不开机。
问题原因:由于在开机后设置了定时时间关机,关机后INT脚电平一直在,导致相当POWER脚一直有按下,不能开机(RTC 电池的存在,INT一直为低),系统上电开机,需要在uboot阶段清中断。
Dts 配置:具体挂在哪路i2c 上,需要结合硬件原理图。
&i2c3 {status = "okay";hym8563: hym8563@51 {status = "okay";compatible = "haoyu,hym8563";reg = <0x51>;#clock-cells = <0>;};};
kernel 阶段:
/** Haoyu HYM8563 RTC driver** Copyright (C) 2013 MundoReader S.L.* Author: Heiko Stuebner <heiko@sntech.de>** based on rtc-HYM8563* Copyright (C) 2010 ROCKCHIP, Inc.** This software is licensed under the terms of the GNU General Public* License version 2, as published by the Free Software Foundation, and* may be copied, distributed, and modified under those terms.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.*/#include <linux/module.h>
#include <linux/clk-provider.h>
#include <linux/i2c.h>
#include <linux/bcd.h>
#include <linux/rtc.h>#define HYM8563_CTL1 0x00
#define HYM8563_CTL1_TEST BIT(7)
#define HYM8563_CTL1_STOP BIT(5)
#define HYM8563_CTL1_TESTC BIT(3)#define HYM8563_CTL2 0x01
#define HYM8563_CTL2_TI_TP BIT(4)
#define HYM8563_CTL2_AF BIT(3)
#define HYM8563_CTL2_TF BIT(2)
#define HYM8563_CTL2_AIE BIT(1)
#define HYM8563_CTL2_TIE BIT(0)#define HYM8563_SEC 0x02
#define HYM8563_SEC_VL BIT(7)
#define HYM8563_SEC_MASK 0x7f#define HYM8563_MIN 0x03
#define HYM8563_MIN_MASK 0x7f#define HYM8563_HOUR 0x04
#define HYM8563_HOUR_MASK 0x3f#define HYM8563_DAY 0x05
#define HYM8563_DAY_MASK 0x3f#define HYM8563_WEEKDAY 0x06
#define HYM8563_WEEKDAY_MASK 0x07#define HYM8563_MONTH 0x07
#define HYM8563_MONTH_CENTURY BIT(7)
#define HYM8563_MONTH_MASK 0x1f#define HYM8563_YEAR 0x08#define HYM8563_ALM_MIN 0x09
#define HYM8563_ALM_HOUR 0x0a
#define HYM8563_ALM_DAY 0x0b
#define HYM8563_ALM_WEEK 0x0c/* Each alarm check can be disabled by setting this bit in the register */
#define HYM8563_ALM_BIT_DISABLE BIT(7)#define HYM8563_CLKOUT 0x0d
#define HYM8563_CLKOUT_ENABLE BIT(7)
#define HYM8563_CLKOUT_32768 0
#define HYM8563_CLKOUT_1024 1
#define HYM8563_CLKOUT_32 2
#define HYM8563_CLKOUT_1 3
#define HYM8563_CLKOUT_MASK 3#define HYM8563_TMR_CTL 0x0e
#define HYM8563_TMR_CTL_ENABLE BIT(7)
#define HYM8563_TMR_CTL_4096 0
#define HYM8563_TMR_CTL_64 1
#define HYM8563_TMR_CTL_1 2
#define HYM8563_TMR_CTL_1_60 3
#define HYM8563_TMR_CTL_MASK 3#define HYM8563_TMR_CNT 0x0fstruct hym8563 {struct i2c_client *client;struct rtc_device *rtc;
#ifdef CONFIG_COMMON_CLKstruct clk_hw clkout_hw;
#endif
};struct hym8563_priv {struct i2c_client *client;unsigned char rtc_int_enable;unsigned char buf[4];
};struct hym8563_priv g_hym8563 = {.client = 0,
};/** RTC handling*/static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
{struct i2c_client *client = to_i2c_client(dev);u8 buf[7];int ret;ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf);tm->tm_sec = bcd2bin(buf[0] & HYM8563_SEC_MASK);tm->tm_min = bcd2bin(buf[1] & HYM8563_MIN_MASK);tm->tm_hour = bcd2bin(buf[2] & HYM8563_HOUR_MASK);tm->tm_mday = bcd2bin(buf[3] & HYM8563_DAY_MASK);tm->tm_wday = bcd2bin(buf[4] & HYM8563_WEEKDAY_MASK); /* 0 = Sun */tm->tm_mon = bcd2bin(buf[5] & HYM8563_MONTH_MASK) - 1; /* 0 = Jan */tm->tm_year = bcd2bin(buf[6]) + 100;return 0;
}static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
{struct i2c_client *client = to_i2c_client(dev);u8 buf[7];int ret;/* Years >= 2100 are to far in the future, 19XX is to early */if (tm->tm_year < 100 || tm->tm_year >= 200)return -EINVAL;buf[0] = bin2bcd(tm->tm_sec);buf[1] = bin2bcd(tm->tm_min);buf[2] = bin2bcd(tm->tm_hour);buf[3] = bin2bcd(tm->tm_mday);buf[4] = bin2bcd(tm->tm_wday);buf[5] = bin2bcd(tm->tm_mon + 1);/** While the HYM8563 has a century flag in the month register,* it does not seem to carry it over a subsequent write/read.* So we'll limit ourself to 100 years, starting at 2000 for now.*/buf[6] = bin2bcd(tm->tm_year - 100);/** CTL1 only contains TEST-mode bits apart from stop,* so no need to read the value first*/ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1,HYM8563_CTL1_STOP);if (ret < 0)return ret;ret = i2c_smbus_write_i2c_block_data(client, HYM8563_SEC, 7, buf);if (ret < 0)return ret;ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0);if (ret < 0)return ret;return 0;
}static int hym8563_rtc_alarm_irq_enable(struct device *dev,unsigned int enabled)
{struct i2c_client *client = to_i2c_client(dev);int data;data = i2c_smbus_read_byte_data(client, HYM8563_CTL2);if (data < 0)return data;if (enabled)data |= HYM8563_CTL2_AIE;elsedata &= ~HYM8563_CTL2_AIE;return i2c_smbus_write_byte_data(client, HYM8563_CTL2, data);
};static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{struct i2c_client *client = to_i2c_client(dev);struct rtc_time *alm_tm = &alm->time;u8 buf[4];int ret;ret = i2c_smbus_read_i2c_block_data(client, HYM8563_ALM_MIN, 4, buf);if (ret < 0)return ret;/* The alarm only has a minute accuracy */alm_tm->tm_sec = 0;alm_tm->tm_min = (buf[0] & HYM8563_ALM_BIT_DISABLE) ?-1 :bcd2bin(buf[0] & HYM8563_MIN_MASK);alm_tm->tm_hour = (buf[1] & HYM8563_ALM_BIT_DISABLE) ?-1 :bcd2bin(buf[1] & HYM8563_HOUR_MASK);alm_tm->tm_mday = (buf[2] & HYM8563_ALM_BIT_DISABLE) ?-1 :bcd2bin(buf[2] & HYM8563_DAY_MASK);alm_tm->tm_wday = (buf[3] & HYM8563_ALM_BIT_DISABLE) ?-1 :bcd2bin(buf[3] & HYM8563_WEEKDAY_MASK);ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);if (ret < 0)return ret;if (ret & HYM8563_CTL2_AIE)alm->enabled = 1;return 0;
}static int hym8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{struct i2c_client *client = to_i2c_client(dev);struct rtc_time *alm_tm = &alm->time;u8 buf[4];int ret;/** The alarm has no seconds so deal with it*/if (alm_tm->tm_sec) {alm_tm->tm_sec = 0;alm_tm->tm_min++;if (alm_tm->tm_min >= 60) {alm_tm->tm_min = 0;alm_tm->tm_hour++;if (alm_tm->tm_hour >= 24) {alm_tm->tm_hour = 0;alm_tm->tm_mday++;alm_tm->tm_wday++;if (alm_tm->tm_wday > 6)alm_tm->tm_wday = 0;switch (alm_tm->tm_mon + 1) {case 1:case 3:case 5:case 7:case 8:case 10:case 12:if (alm_tm->tm_mday > 31)alm_tm->tm_mday = 1;break;case 4:case 6:case 9:case 11:if (alm_tm->tm_mday > 30)alm_tm->tm_mday = 1;break;case 2:if (alm_tm->tm_year / 4 == 0) {if (alm_tm->tm_mday > 29)alm_tm->tm_mday = 1;} else if (alm_tm->tm_mday > 28) {alm_tm->tm_mday = 1;}break;}}}}printk("%s\n,tm_min=%d,tm_hour=%d,tm_mday=%d,tm_wday=%d,enabled=%d\n",__func__,alm_tm->tm_min,alm_tm->tm_hour,alm_tm->tm_mday,alm_tm->tm_wday,alm->enabled);ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);if (ret < 0)return ret;ret &= ~HYM8563_CTL2_AIE;//ret |= HYM8563_CTL2_AIE;ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret);if (ret < 0)return ret;buf[0] = (alm_tm->tm_min < 60 && alm_tm->tm_min >= 0) ?bin2bcd(alm_tm->tm_min) : HYM8563_ALM_BIT_DISABLE;buf[1] = (alm_tm->tm_hour < 24 && alm_tm->tm_hour >= 0) ?bin2bcd(alm_tm->tm_hour) : HYM8563_ALM_BIT_DISABLE;buf[2] = (alm_tm->tm_mday <= 31 && alm_tm->tm_mday >= 1) ?bin2bcd(alm_tm->tm_mday) : HYM8563_ALM_BIT_DISABLE;buf[3] = (alm_tm->tm_wday < 7 && alm_tm->tm_wday >= 0) ?bin2bcd(alm_tm->tm_wday) : HYM8563_ALM_BIT_DISABLE;if(alm->enabled){g_hym8563.buf[0] = buf[0];g_hym8563.buf[1] = buf[1];g_hym8563.buf[2] = buf[2];g_hym8563.buf[3] = buf[3];g_hym8563.rtc_int_enable = 1;printk("##fan## %s save alarm time\n",__func__);return 0;}ret = i2c_smbus_write_i2c_block_data(client, HYM8563_ALM_MIN, 4, buf);if (ret < 0)return ret;return hym8563_rtc_alarm_irq_enable(dev, alm->enabled);
}static int hym8563_rtc_alarm_irq_enable1(struct i2c_client *client,unsigned int enabled)
{int data;data = i2c_smbus_read_byte_data(client, HYM8563_CTL2);if (data < 0)return data;printk("#### %s ######### enabled=%d before data=%0x \n",__func__,enabled,data);if (enabled)data |= HYM8563_CTL2_AIE;elsedata &= ~HYM8563_CTL2_AIE;data &= ~HYM8563_CTL2_AF;printk("#### %s ######### enabled=%d after data=%0x \n",__func__,enabled,data);return i2c_smbus_write_byte_data(client, HYM8563_CTL2, data);
};void hym8563_system_power_off_set_alarm(void)
{struct i2c_client *client = g_hym8563.client;unsigned char buf[4];int ret;printk("### %s ######### rtc_int_enable=%d\n",__func__,g_hym8563.rtc_int_enable);if(g_hym8563.client == 0){printk("#### %s can't find hym8563 i2c client\n",__func__);return;}if(g_hym8563.rtc_int_enable){buf[0] = g_hym8563.buf[0];buf[1] = g_hym8563.buf[1];buf[2] = g_hym8563.buf[2];buf[3] = g_hym8563.buf[3];ret = i2c_smbus_write_i2c_block_data(client, HYM8563_ALM_MIN, 4, buf);if(ret < 0)return;hym8563_rtc_alarm_irq_enable1(client, !!g_hym8563.rtc_int_enable);}
}static const struct rtc_class_ops hym8563_rtc_ops = {.read_time = hym8563_rtc_read_time,.set_time = hym8563_rtc_set_time,.alarm_irq_enable = hym8563_rtc_alarm_irq_enable,.read_alarm = hym8563_rtc_read_alarm,.set_alarm = hym8563_rtc_set_alarm,
};/** Handling of the clkout*/#ifdef CONFIG_COMMON_CLK
#define clkout_hw_to_hym8563(_hw) container_of(_hw, struct hym8563, clkout_hw)static int clkout_rates[] = {32768,1024,32,1,
};static unsigned long hym8563_clkout_recalc_rate(struct clk_hw *hw,unsigned long parent_rate)
{struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);struct i2c_client *client = hym8563->client;int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);if (ret < 0)return 0;ret &= HYM8563_CLKOUT_MASK;return clkout_rates[ret];
}static long hym8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate,unsigned long *prate)
{int i;for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)if (clkout_rates[i] <= rate)return clkout_rates[i];return 0;
}static int hym8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,unsigned long parent_rate)
{struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);struct i2c_client *client = hym8563->client;int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);int i;if (ret < 0)return ret;for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)if (clkout_rates[i] == rate) {ret &= ~HYM8563_CLKOUT_MASK;ret |= i;return i2c_smbus_write_byte_data(client,HYM8563_CLKOUT, ret);}return -EINVAL;
}static int hym8563_clkout_control(struct clk_hw *hw, bool enable)
{struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);struct i2c_client *client = hym8563->client;int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);if (ret < 0)return ret;if (enable)ret |= HYM8563_CLKOUT_ENABLE;elseret &= ~HYM8563_CLKOUT_ENABLE;return i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, ret);
}static int hym8563_clkout_prepare(struct clk_hw *hw)
{return hym8563_clkout_control(hw, 1);
}static void hym8563_clkout_unprepare(struct clk_hw *hw)
{hym8563_clkout_control(hw, 0);
}static int hym8563_clkout_is_prepared(struct clk_hw *hw)
{struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);struct i2c_client *client = hym8563->client;int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);if (ret < 0)return ret;return !!(ret & HYM8563_CLKOUT_ENABLE);
}static const struct clk_ops hym8563_clkout_ops = {.prepare = hym8563_clkout_prepare,.unprepare = hym8563_clkout_unprepare,.is_prepared = hym8563_clkout_is_prepared,.recalc_rate = hym8563_clkout_recalc_rate,.round_rate = hym8563_clkout_round_rate,.set_rate = hym8563_clkout_set_rate,
};static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563)
{struct i2c_client *client = hym8563->client;struct device_node *node = client->dev.of_node;struct clk *clk;struct clk_init_data init = {};int ret;ret = i2c_smbus_write_byte_data(client, HYM8563_CLKOUT,0);if (ret < 0)return ERR_PTR(ret);init.name = "hym8563-clkout";init.ops = &hym8563_clkout_ops;init.flags = 0;init.parent_names = NULL;init.num_parents = 0;hym8563->clkout_hw.init = &init;/* optional override of the clockname */of_property_read_string(node, "clock-output-names", &init.name);/* register the clock */clk = clk_register(&client->dev, &hym8563->clkout_hw);if (!IS_ERR(clk))of_clk_add_provider(node, of_clk_src_simple_get, clk);return clk;
}
#endif/** The alarm interrupt is implemented as a level-low interrupt in the* hym8563, while the timer interrupt uses a falling edge.* We don't use the timer at all, so the interrupt is requested to* use the level-low trigger.*/
static irqreturn_t hym8563_irq(int irq, void *dev_id)
{struct hym8563 *hym8563 = (struct hym8563 *)dev_id;struct i2c_client *client = hym8563->client;struct mutex *lock = &hym8563->rtc->ops_lock;int data, ret;mutex_lock(lock);/* Clear the alarm flag */data = i2c_smbus_read_byte_data(client, HYM8563_CTL2);if (data < 0) {dev_err(&client->dev, "%s: error reading i2c data %d\n",__func__, data);goto out;}data &= ~HYM8563_CTL2_AF;ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, data);if (ret < 0) {dev_err(&client->dev, "%s: error writing i2c data %d\n",__func__, ret);}out:mutex_unlock(lock);return IRQ_HANDLED;
}static int hym8563_init_device(struct i2c_client *client)
{int ret;int i;/* Clear stop flag if present */for(i=0;i<5;i++){ret = i2c_smbus_read_byte_data(client, HYM8563_CTL1);if(ret>=0)break;}ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0);if (ret < 0)return ret;ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);if (ret < 0)return ret;/* Disable alarm and timer interrupts */ret &= ~HYM8563_CTL2_AIE;ret &= ~HYM8563_CTL2_TIE;/* Clear any pending alarm and timer flags */if (ret & HYM8563_CTL2_AF)ret &= ~HYM8563_CTL2_AF;if (ret & HYM8563_CTL2_TF)ret &= ~HYM8563_CTL2_TF;ret &= ~HYM8563_CTL2_TI_TP;return i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret);
}#ifdef CONFIG_PM_SLEEP
static int hym8563_suspend(struct device *dev)
{struct i2c_client *client = to_i2c_client(dev);int ret;if (device_may_wakeup(dev)) {ret = enable_irq_wake(client->irq);if (ret) {dev_err(dev, "enable_irq_wake failed, %d\n", ret);return ret;}}return 0;
}static int hym8563_resume(struct device *dev)
{struct i2c_client *client = to_i2c_client(dev);if (device_may_wakeup(dev))disable_irq_wake(client->irq);return 0;
}
#endifstatic SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume);static int hym8563_probe(struct i2c_client *client,const struct i2c_device_id *id)
{struct hym8563 *hym8563;int ret;/** hym8563 initial time(2021_1_1_12:00:00),* avoid hym8563 read time error*/struct rtc_time tm_read, tm = {.tm_wday = 0,.tm_year = 121,.tm_mon = 0,.tm_mday = 1,.tm_hour = 12,.tm_min = 0,.tm_sec = 0,};g_hym8563.client = client;g_hym8563.rtc_int_enable = 0;hym8563 = devm_kzalloc(&client->dev, sizeof(*hym8563), GFP_KERNEL);if (!hym8563)return -ENOMEM;hym8563->client = client;i2c_set_clientdata(client, hym8563);ret = hym8563_init_device(client);if (ret) {dev_err(&client->dev, "could not init device, %d\n", ret);return ret;}if (client->irq > 0) {ret = devm_request_threaded_irq(&client->dev, client->irq,NULL, hym8563_irq,IRQF_TRIGGER_LOW | IRQF_ONESHOT,client->name, hym8563);if (ret < 0) {dev_err(&client->dev, "irq %d request failed, %d\n",client->irq, ret);return ret;}}if (client->irq > 0 ||device_property_read_bool(&client->dev, "wakeup-source")) {device_init_wakeup(&client->dev, true);}/* check state of calendar information */ret = i2c_smbus_read_byte_data(client, HYM8563_SEC);if (ret < 0)return ret;dev_info(&client->dev, "rtc information is %s\n",(ret & HYM8563_SEC_VL) ? "invalid" : "valid");hym8563_rtc_read_time(&client->dev, &tm_read);if ((ret & HYM8563_SEC_VL) || (tm_read.tm_year < 70) || (tm_read.tm_year > 200) ||(tm_read.tm_mon == -1) || (rtc_valid_tm(&tm_read) != 0))hym8563_rtc_set_time(&client->dev, &tm);hym8563->rtc = devm_rtc_device_register(&client->dev, client->name,&hym8563_rtc_ops, THIS_MODULE);if (IS_ERR(hym8563->rtc))return PTR_ERR(hym8563->rtc);/* the hym8563 alarm only supports a minute accuracy */hym8563->rtc->uie_unsupported = 1;#ifdef CONFIG_COMMON_CLKhym8563_clkout_register_clk(hym8563);
#endifreturn 0;
}static const struct i2c_device_id hym8563_id[] = {{ "hym8563", 0 },{},
};
MODULE_DEVICE_TABLE(i2c, hym8563_id);static const struct of_device_id hym8563_dt_idtable[] = {{ .compatible = "haoyu,hym8563" },{},
};
MODULE_DEVICE_TABLE(of, hym8563_dt_idtable);static struct i2c_driver hym8563_driver = {.driver = {.name = "rtc-hym8563",.pm = &hym8563_pm_ops,.of_match_table = hym8563_dt_idtable,},.probe = hym8563_probe,.id_table = hym8563_id,
};module_i2c_driver(hym8563_driver);MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
MODULE_DESCRIPTION("HYM8563 RTC driver");
MODULE_LICENSE("GPL");
由于在开机后设置了定时时间关机,关机后INT脚电平一直在,导致相当POWER脚一直有按下,不能开机(RTC 电池的存在,INT一直为低),系统上电开机,需要在uboot阶段清中断。
ret &= ~HYM8563_CTL2_AIE;ret &= ~HYM8563_CTL2_TIE;/* Clear any pending alarm and timer flags */if (ret & HYM8563_CTL2_AF)ret &= ~HYM8563_CTL2_AF;if (ret & HYM8563_CTL2_TF)ret &= ~HYM8563_CTL2_TF;ret &= ~HYM8563_CTL2_TI_TP;printf_info("#### %s ret=0x%x\n",__func__,ret);return i2c_write_byte_data(HYM8563_CTL2, ret);
Uboot. 阶段
//
/** (C) Copyright 2008-2018 Youngfel Electronics Co., Ltd*/#include <common.h>
#include <dm.h>
#include <dm/device-internal.h>
#include <errno.h>
#include <i2c.h>
#include <linux/media-bus-format.h>
//#include "rtc_iic.h"#define HYM8563_CTL1 0x00
#define HYM8563_CTL1_TEST BIT(7)
#define HYM8563_CTL1_STOP BIT(5)
#define HYM8563_CTL1_TESTC BIT(3)#define HYM8563_CTL2 0x01
#define HYM8563_CTL2_TI_TP BIT(4)
#define HYM8563_CTL2_AF BIT(3)
#define HYM8563_CTL2_TF BIT(2)
#define HYM8563_CTL2_AIE BIT(1)
#define HYM8563_CTL2_TIE BIT(0)struct udevice *rtc_i2c_dev;#ifdef DEBUG
#define printf_info(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define printf_info(fmt, ...)
#endifint rtc_write(struct udevice *dev, uint reg, const uint8_t *buff,int len)
{return dm_i2c_write(dev, reg, buff, len);
}static int rtc_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
{return dm_i2c_read(dev, reg, buff, len);
}int i2c_read_byte_data(u8 command)
{uint8_t value = 0;int ret =0;ret = rtc_read(rtc_i2c_dev,command,&value,1);if(ret < 0){printf("rtc read error\n");return ret;}else{printf("rtc read value=%d\n",value);return value;}}
int i2c_write_byte_data(u8 command, u8 value)
{int ret =0;ret = rtc_write(rtc_i2c_dev, command, &value,1);if(ret < 0)printf("rtc write error\n");return ret;}#ifdef CONFIG_POWER_ON_STYLE_SUPPORT
extern char IsAllowPower;
#endifstatic int hym8563_init_device(void)
{int ret;int i;int reg_value = 0;/* Clear stop flag if present */printf_info("##fan## %s\n",__func__);for(i=0;i<5;i++){ret = i2c_read_byte_data(HYM8563_CTL1);if(ret>=0)break;}reg_value = i2c_read_byte_data(HYM8563_CTL2);printf("#### %s,rtc_int_value=0x%x\n",__func__,reg_value);if (reg_value < 0)return reg_value;if(HYM8563_CTL2_AIE & reg_value){if(reg_value & HYM8563_CTL2_AF){IsAllowPower = 1;printf("#### rtc alarm power on\n");}}ret = i2c_write_byte_data(HYM8563_CTL1, 0);if (ret < 0)return ret;ret = i2c_read_byte_data(HYM8563_CTL2);if (ret < 0)return ret;/* Disable alarm and timer interrupts */ret &= ~HYM8563_CTL2_AIE;ret &= ~HYM8563_CTL2_TIE;/* Clear any pending alarm and timer flags */if (ret & HYM8563_CTL2_AF)ret &= ~HYM8563_CTL2_AF;if (ret & HYM8563_CTL2_TF)ret &= ~HYM8563_CTL2_TF;ret &= ~HYM8563_CTL2_TI_TP;printf_info("#### %s ret=0x%x\n",__func__,ret);return i2c_write_byte_data(HYM8563_CTL2, ret);
}static int rtc_probe(struct udevice *dev)
{rtc_i2c_dev = dev;printf(" init rtc_probe \n");hym8563_init_device();return 0;
}static const struct udevice_id rtc_of_match[] = {{ .compatible = "nxp,pcf8563" },{ .compatible = "haoyu,hym8563" },{},
};U_BOOT_DRIVER(hym8563) = {.name = "hym8563",.id = UCLASS_I2C_GENERIC,.of_match = rtc_of_match,.probe = rtc_probe,.bind = dm_scan_fdt_dev,
};
Mobile:+86 19926489508/13077808909(Wechat微信同号)
QQ交流群: 712288614