1,vivado硬件工程并加约束,导入sdk生成*.hdf
set_property SEVERITY {Warning} [get_drc_checks UCIO-1]
set_property PACKAGE_PIN L15 [get_ports IIC0_scl_io]
set_property PACKAGE_PIN L14 [get_ports IIC0_sda_io]
set_property IOSTANDARD LVCMOS33 [get_ports IIC0_scl_io]
set_property IOSTANDARD LVCMOS33 [get_ports IIC0_sda_io]
set_property PACKAGE_PIN P20 [get_ports IIC1_scl_io]
set_property PACKAGE_PIN P21 [get_ports IIC1_sda_io]
set_property IOSTANDARD LVCMOS33 [get_ports IIC1_scl_io]
set_property IOSTANDARD LVCMOS33 [get_ports IIC1_sda_io]
2,petalinux-config --get-hw-description ../linux_base.sdk 导入硬件
3,添加驱动并编译编译内核
进入driver/rtc下,加入1302驱动drv_ds1302.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/rtc.h>
#define RTC_SET_DATE 0x0c
#define RTC_SET_TIME 0x08
#define RTC_GET_DATE 0x04
#define RTC_GET_TIME 0x00
struct ax_rtc_ds1302_dev {
struct rtc_device *rtc;
void __iomem *reg_base;
int alarm_irq;
int sec_irq;
int calibval;
};
static int ax_rtc_ds1302_set_time(struct device *dev, struct rtc_time *tm)
{
struct ax_rtc_ds1302_dev *xrtcdev = dev_get_drvdata(dev);
u32 utime, udate;
u32 tempY = ((tm->tm_year)/10*16+(tm->tm_year)%10)<<16;
u32 tempM = (tm->tm_mon/10*16+tm->tm_mon%10)<<8;
u32 tempD = (tm->tm_mday/10*16+tm->tm_mday%10);
udate = tempY + tempM + tempD + 0x80000000;
u32 tempH = (tm->tm_hour/10*16+ tm->tm_hour%10)<<16;
u32 tempI = (tm->tm_min/10*16+tm->tm_min%10)<<8;
u32 tempS = tm->tm_sec;
utime = tempH + tempI + tempS;
writel(udate, xrtcdev->reg_base + RTC_SET_DATE);
writel(utime, xrtcdev->reg_base + RTC_SET_TIME);
return 1;
}
static int ax_rtc_ds1302_read_time(struct device *dev, struct rtc_time *tm)
{
struct ax_rtc_ds1302_dev *xrtcdev = dev_get_drvdata(dev);
u32 utime = readl(xrtcdev->reg_base + RTC_GET_TIME);
u32 udate = readl(xrtcdev->reg_base + RTC_GET_DATE);
u8 temp = (unsigned char)(udate >> 16);
tm->tm_year = temp/16*10 + temp%16 ;
temp = (unsigned char)(udate >> 8);
tm->tm_mon = temp/16*10 + temp%16;
temp = (unsigned char)(udate);
tm->tm_mday = temp/16*10 + temp%16;;
temp = (unsigned char)(utime >> 16);
tm->tm_hour = temp/16*10 + temp%16;
temp = (unsigned char)(utime >> 8);
tm->tm_min = temp/16*10 + temp%16;
temp = (unsigned char)(utime);
tm->tm_sec= temp/16*10 + temp%16;
if(rtc_valid_tm(tm)<0)
{
tm->tm_year = 117;
tm->tm_mon = 11;
tm->tm_mday = 10;
tm->tm_hour = 13;
tm->tm_min = 0;
tm->tm_sec = 0;
ax_rtc_ds1302_set_time(dev,tm);
}
return rtc_valid_tm(tm);
}
static const struct rtc_class_ops ax_rtc_ops =
{
.set_time = ax_rtc_ds1302_set_time,
.read_time = ax_rtc_ds1302_read_time,
};
static int ax_rtc_ds1302_probe(struct platform_device *pdev)
{
struct ax_rtc_ds1302_dev *xrtcdev;
struct resource *res;
int ret;
xrtcdev = devm_kzalloc(&pdev->dev, sizeof(*xrtcdev), GFP_KERNEL);
if(!xrtcdev)
return -ENOMEM;
platform_set_drvdata(pdev, xrtcdev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if(res == NULL)
{
return -ENOENT;
}
xrtcdev->reg_base = devm_ioremap_resource(&pdev->dev,res);
if(IS_ERR(xrtcdev->reg_base))
{
return PTR_ERR(xrtcdev->reg_base);
}
device_init_wakeup(&pdev->dev, 1);
xrtcdev->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&ax_rtc_ops, THIS_MODULE);
return PTR_ERR_OR_ZERO(xrtcdev->rtc);
}
static int ax_rtc_ds1302_remove(struct platform_device *pdev)
{
device_init_wakeup(&pdev->dev, 0);
return 0;
}
static int __maybe_unused ax_rtc_ds1302_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct ax_rtc_ds1302_dev *xrtcdev = platform_get_drvdata(pdev);
return 0;
}
static int __maybe_unused ax_rtc_ds1302_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct ax_rtc_ds1302_dev *xrtcdev = platform_get_drvdata(pdev);
return 0;
}
static SIMPLE_DEV_PM_OPS(ax_rtc_ds1302_pm_ops, ax_rtc_ds1302_suspend, ax_rtc_ds1302_resume);
static const struct of_device_id ax_rtc_ds1302_of_match[] = {
{.compatible = "alinx,ax-rtc-ds1302" },
{ }
};
MODULE_DEVICE_TABLE(of, ax_rtc_ds1302_of_match);
static struct platform_driver ax_rtc_ds1302_driver = {
.probe = ax_rtc_ds1302_probe,
.remove = ax_rtc_ds1302_remove,
.driver = {
.name = KBUILD_MODNAME,
.pm = &ax_rtc_ds1302_pm_ops,
.of_match_table = ax_rtc_ds1302_of_match,
},
};
module_platform_driver(ax_rtc_ds1302_driver);
MODULE_DESCRIPTION("Alinx DS1302 RTC driver");
MODULE_AUTHOR("Guowc.");
MODULE_LICENSE("GPL v2");
(2)在driver/rtc下的makefile增加一句
obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
(3)在driver/rtc下的kconfig增加一句
config RTC_DRV_DS1302
tristate "Dallas/Maxim DS1302"
depends on SPI
help
If you say yes here you get support for the Dallas DS1302 RTC chips.
This driver can also be built as a module. If so, the module
will be called rtc-ds1302.
(4)选择对应rtc驱动并保存 petalinux-config -c kernel
Device Driver->Real Time Clock->Alinx DS1302
5,修改设备树
xilinx_drm
{
compatible = "xlnx,drm";
xlnx,vtc = <0x9>;
xlnx,connector-type = "HDMIA";
xlnx,encoder-slave = <0xa>;
clocks = <0xb>;
dglnt,edid-i2c = <0x8>;
planes
{
xlnx,pixel-format = "xrgb8888";
plane0
{
dmas = <0xc 0x0>;
dma-names = "dma";
};
};
};
digilent_encoder
{
compatible = "dglnt,drm-encoder";
dglnt,edid-i2c = <0x8>;
linux,phandle = <0xa>;
phandle = <0xa>;
};
ax_rtc
{
compatible = "alinx,ax-rtc-ds1302";
reg = <0x43C20000 0x1000>;
};
};
6,编译petalinux-build,并把启动文件放入sd卡