ARM11 paltform驱动代码完成,最简单的测试直接在装载设备中运行,实现秒读 顶 原

信息 77浏览

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/clk.h>
#include <linux/log2.h>
#include <linux/slab.h>
#include <linux/rtc.h>
#include <linux/ioport.h>
#include <linux/delay.h> 

#include <mach/hardware.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <plat/regs-rtc.h>
#include <plat/devs.h>
#include <mach/map.h>

struct resource *yzh_rtc_mem;
struct clk *rtc_clk;
//struct rtc_device *rtc;
struct rtc_time rtc_test;

static void __iomem *rtc_reg_base;
//(*(volatile unsigned long *)
#define rtc_reg(x) (rtc_reg_base + x)

int yzh_rtc_open(struct device *dev)
{
 int temp = 0;

 temp = readb(rtc_reg(S3C2410_RTCCON));
 temp |= S3C2410_RTCCON_RTCEN;
 writeb(temp,rtc_reg(S3C2410_RTCCON));

 temp = readb(rtc_reg(S3C2410_RTCCON));
 temp &= ~(S3C2410_RTCCON_CNTSEL);
 writeb(temp,rtc_reg(S3C2410_RTCCON));

 temp = readb(rtc_reg(S3C2410_RTCCON));
 temp &= ~(S3C2410_RTCCON_CLKRST);
 writeb(temp,rtc_reg(S3C2410_RTCCON));

 temp = readb(rtc_reg(S3C2410_RTCCON));
 temp |= S3C64XX_RTCCON_TICEN;
 writeb(temp,rtc_reg(S3C2410_RTCCON));

 temp = readb(rtc_reg(S3C2410_RTCCON));
 temp |= 0 << 4;
 writeb(temp,rtc_reg(S3C2410_RTCCON));

 printk("yzh rtc is open nr");

 return 0;
}
 
static void yzh_rtc_release(struct device *dev)
{
 int temp = 0;
 
 temp = readb(rtc_reg(S3C2410_RTCCON));
 temp &= ~S3C2410_RTCCON_RTCEN;
 writeb(temp,rtc_reg(S3C2410_RTCCON)); //stop RTC

 temp = readb(rtc_reg(S3C2410_RTCCON));
 temp &= ~S3C64XX_RTCCON_TICEN;
 writeb(temp,rtc_reg(S3C2410_RTCCON));
 
 
 printk("the yzh rtc release nr");
}

int yzh_rtc_set_time(struct device *dev, struct rtc_time *rtc_set)
{
 //set time: 2013-11-22 23:59:30

 rtc_set -> tm_sec = 30;
 rtc_set -> tm_min = 59;
 rtc_set -> tm_hour = 23;
 rtc_set -> tm_mday = 22;
 rtc_set -> tm_mon = 11;
// rtc_set -> tm_year += 113;
 rtc_set -> tm_year = 0;

 writeb(bin2bcd(rtc_set -> tm_sec),rtc_reg(S3C2410_RTCSEC));
 writeb(bin2bcd(rtc_set -> tm_min),rtc_reg(S3C2410_RTCMIN));
 writeb(bin2bcd(rtc_set -> tm_hour),rtc_reg(S3C2410_RTCHOUR));
 writeb(bin2bcd(rtc_set -> tm_mday),rtc_reg(S3C2410_RTCDAY));
 writeb(bin2bcd(rtc_set -> tm_mon),rtc_reg(S3C2410_RTCMON));
 writeb(bin2bcd(rtc_set -> tm_year),rtc_reg(S3C2410_RTCYEAR));

 printk("time has seted nr");
 return 0;
}

int yzh_rtc_read_time(struct device *dev, struct rtc_time *read_time)
{
 read_time -> tm_sec = bcd2bin(readb(rtc_reg(S3C2410_RTCSEC)));
 read_time -> tm_min = bcd2bin(readb(rtc_reg(S3C2410_RTCMIN)));
 read_time -> tm_hour = bcd2bin(readb(rtc_reg(S3C2410_RTCHOUR)));
 read_time -> tm_mday = bcd2bin(readb(rtc_reg(S3C2410_RTCDAY)));
 read_time -> tm_mon = bcd2bin(readb(rtc_reg(S3C2410_RTCMON)));
 read_time -> tm_year = bcd2bin(readb(rtc_reg(S3C2410_RTCYEAR)));

 printk("time:%d-%d-%d %d:%d:%d nr",read_time -> tm_year,read_time -> tm_mon,read_time -> tm_mday,read_time -> tm_hour,read_time -> tm_min,read_time -> tm_sec);
 
 return 0;
}

struct rtc_class_ops yzh_rtc_ops = {
 .open = yzh_rtc_open,
 .release = yzh_rtc_release,
 .set_time = yzh_rtc_set_time,
 .read_time = yzh_rtc_read_time,
// .proc = ,
 
};

static void yzh_rtc_test(void)
{
 int i; 
 yzh_rtc_open(NULL);
 yzh_rtc_set_time(NULL,&rtc_test);
 for(i=0;i<50;i++)
 { 
  yzh_rtc_read_time(NULL,&rtc_test);
  mdelay(500);mdelay(500);
 }
}

int yzh_rtc_probe(struct platform_device *pdev)
{
  
 struct resource *res;

/* yzh_systick_irq = platform_get_irq(pdev,1);
 if(yzh_systick_irq < 0)
 {
  printk("yzh_systick_irq is fail nr");
  return 0;
 }*/

 res = platform_get_resource(pdev,IORESOURCE_MEM,0);
 if(res == NULL)
 {
  printk("res resource fail nr");
  return 0;
 }

 yzh_rtc_mem = request_mem_region(res -> start,res -> end - res -> start + 1, pdev -> name);
 if(yzh_rtc_mem == NULL)
 {
  printk("yzh_rtc_mem fail nr");
  return 0;
 }

 rtc_reg_base = ioremap(res -> start,res -> end - res -> start + 1);
 if(rtc_reg_base == NULL)
 {
  printk("rtc_reg_base iomem has fail nr");
  return 0;
 }
 
 rtc_clk = clk_get(&pdev -> dev,"yzh_rtc_clk"); 
 if(rtc_clk == NULL)
 {
  printk("rtc_clk is not get nr");
  return 0;
 }

 clk_enable(rtc_clk);
// rtc = rtc_device_register("yzh_rtc_device",&pdev -> dev,&yzh_rtc_ops,THIS_MODULE);

 return 0;
}

int yzh_rtc_remove(struct platform_device *pdev)
{
// rtc_device_unregister(rtc);

// clk_disable(rtc_clk);
// clk_put(rtc_clk);
// rtc_clk = NULL;

 iounmap(rtc_reg_base);
 release_resource(yzh_rtc_mem);
 kfree(yzh_rtc_mem);

 printk("yzh_rtc_remove nr");
 
 return 0;
}

/*struct platform_device_id yzh_rtc_ids[] = {
 {
  .name = "s3c64xx-rtc",
 },{},
};

MODULE_DEVICE_TABLE(platform, yzh_rtc_ids);*/

static struct platform_driver s3c_rtc_driver = {
 .probe = yzh_rtc_probe,
 .remove = yzh_rtc_remove,
// .id_table = yzh_rtc_ids,
 
 .driver = {
  .name = "s3c64xx-rtc",
  .owner = THIS_MODULE,
 },
};

static int rtc_init(void)
{
 int ret;
 ret = platform_driver_register(&s3c_rtc_driver); 
 yzh_rtc_test();
 printk("the rtc module has install nr");   
 return ret;
}

static void  rtc_exit(void)

 platform_driver_unregister(&s3c_rtc_driver);
 printk("the rtc module has uninstall nr");   
}

module_init(rtc_init);
module_exit(rtc_exit);
MODULE_LICENSE("GPL");