硬件修改版本后将原来用的rtc ds1307芯片换成了ht1382,导致系统无法启动。接下来准备在ds1307驱动中增加ht1382的驱动。

1 DS1307与HT1382的寄存器差异

DS1307 register:
****HT1382 register:
note: 红色框的内容是两种芯片差异的部分

2 增加HT1382驱动

在设备类型中增加我们的rtc芯片:

/** We can't determine type by probing, but if we expect pre-Linux code* to have set the chip up as a clock (turning on the oscillator and* setting the date and time), Linux can ignore the non-clock features.* That's a natural job for a factory or repair bench.*/
enum ds_type {ds_1307,ds_1337,ds_1338,ds_1339,ds_1340,ds_1388,ds_3231,m41t00,mcp794xx,rx_8025,ht_1382, /*add rtc ht1382 type*/last_ds_type /* always last *//* rs5c372 too?  different address... */
};

根据HT1382寄存器手册增加宏定义:

/****************add ht1382 register define****************/
#define HT1382_REG_MDAY 0x03    /* 01-31 */
#define HT1382_REG_MONTH    0x04    /* 01-12 */
#define HT1382_REG_WDAY 0x05    /* 01-07 */
#define HT1382_REG_WP       0x07
#   define HT1382_BIT_WP        0x80
/********************add end**********************/

增加芯片描述:

static struct chip_desc chips[last_ds_type] = {[ds_1307] = {.nvram_offset  = 8,.nvram_size    = 56,},/*add ht1382 chip desc, same as ds1307*/[ht_1382] = {.nvram_offset = 8,.nvram_size    = 56,},[ds_1337] = {.alarm        = 1,},[ds_1338] = {.nvram_offset  = 8,.nvram_size    = 56,},[ds_1339] = {.alarm        = 1,.trickle_charger_reg = 0x10,.do_trickle_setup = &do_trickle_setup_ds1339,},[ds_1340] = {.trickle_charger_reg = 0x08,},[ds_1388] = {.trickle_charger_reg = 0x0a,},[ds_3231] = {.alarm        = 1,},[mcp794xx] = {.alarm        = 1,/* this is battery backed SRAM */.nvram_offset = 0x20,.nvram_size = 0x40,},
};

增加ht1382 device id:

static const struct i2c_device_id ds1307_id[] = {{ "ds1307", ds_1307 },{ "ds1337", ds_1337 },{ "ds1338", ds_1338 },{ "ds1339", ds_1339 },{ "ds1388", ds_1388 },{ "ds1340", ds_1340 },{ "ds3231", ds_3231 },{ "m41t00", m41t00 },{ "mcp7940x", mcp794xx },{ "mcp7941x", mcp794xx },{ "pt7c4338", ds_1307 },{ "rx8025", rx_8025 },/*dts compatible should be set "dallas,ht1382"*/{ "ht1382", ht_1382 },{ }
};

以上是需要在数据结构中添加的一些东西。

然后在添加驱动时需要注意,HT1382比DS1307多了一个Write Protect寄存器,我们可以在设备probe时直接设置关掉,或者仅在用户调用写时间函数时关闭写保护,此处笔者选择的前者:

static int ds1307_probe(struct i2c_client *client,const struct i2c_device_id *id)
{struct ds1307      *ds1307;int         err = -ENODEV;int          tmp;struct chip_desc    *chip = &chips[id->driver_data];struct i2c_adapter  *adapter = to_i2c_adapter(client->dev.parent);....................if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {ds1307->read_block_data = ds1307_native_smbus_read_block_data;ds1307->write_block_data = ds1307_native_smbus_write_block_data;} else {ds1307->read_block_data = ds1307_read_block_data;ds1307->write_block_data = ds1307_write_block_data;}switch (ds1307->type) {/*add ht1382 driver for close write protect*/case ht_1382:/* check write protect reg */tmp = ds1307->read_block_data(ds1307->client,HT1382_REG_WP, 2, &(ds1307->regs[HT1382_REG_WP]));if(tmp != 2){dev_dbg(&client->dev, "read error %d\n", tmp);err = -EIO;goto exit;}if (ds1307->regs[HT1382_REG_WP] & HT1382_BIT_WP){ds1307->regs[HT1382_REG_WP] &= ~HT1382_BIT_WP;i2c_smbus_write_byte_data(client, HT1382_REG_WP,ds1307->regs[HT1382_REG_WP]);}break;case ds_1337:case ds_1339:case ds_3231:/* get registers that the "rtc" read below won't read... */tmp = ds1307->read_block_data(ds1307->client,DS1337_REG_CONTROL, 2, buf);

在probe函数中还有一处是需要检查Clock HALT 的,我们需要给ht1382也加上:

 /** minimal sanity checking; some chips (like DS1340) don't* specify the extra bits as must-be-zero, but there are* still a few values that are clearly out-of-range.*/tmp = ds1307->regs[DS1307_REG_SECS];switch (ds1307->type) {case ds_1307:case ht_1382:case m41t00:/* clock halted?  turn it on, so clock can tick. */if (tmp & DS1307_BIT_CH) {i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);dev_warn(&client->dev, "SET TIME!\n");goto read_rtc;}break;

由于HT1382的月份,日期和星期的寄存器和DS1307不太相同,所以我们还需要修改ds13xx_rtc_ops中的read_time和set_time

static const struct rtc_class_ops ds13xx_rtc_ops = {.read_time  = ds1307_get_time, //need modify.set_time  = ds1307_set_time, //need modify.read_alarm    = ds1337_read_alarm,.set_alarm = ds1337_set_alarm,.alarm_irq_enable = ds1307_alarm_irq_enable,
};

修改ds1307_get_time函数:

static int ds1307_get_time(struct device *dev, struct rtc_time *t)
{struct ds1307  *ds1307 = dev_get_drvdata(dev);int     tmp;/* read the RTC date and time registers all at once */tmp = ds1307->read_block_data(ds1307->client,ds1307->offset, 7, ds1307->regs);if (tmp != 7) {dev_err(dev, "%s error %d\n", "read", tmp);return -EIO;}dev_dbg(dev, "%s: %7ph\n", "read", ds1307->regs);t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f);t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f;t->tm_hour = bcd2bin(tmp);/*add ht1382*/switch (ds1307->type) {case ht_1382:t->tm_wday = bcd2bin(ds1307->regs[HT1382_REG_WDAY] & 0x07) - 1;t->tm_mday = bcd2bin(ds1307->regs[HT1382_REG_MDAY] & 0x3f);tmp = ds1307->regs[HT1382_REG_MONTH] & 0x1f;t->tm_mon = bcd2bin(tmp) - 1;break;default:t->tm_wday = bcd2bin(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1;t->tm_mday = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f);tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f;t->tm_mon = bcd2bin(tmp) - 1;break;}/*add end*//* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */t->tm_year = bcd2bin(ds1307->regs[DS1307_REG_YEAR]) + 100;dev_dbg(dev, "%s secs=%d, mins=%d, ""hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n","read", t->tm_sec, t->tm_min,t->tm_hour, t->tm_mday,t->tm_mon, t->tm_year, t->tm_wday);/* initial clock setting can be undefined */return rtc_valid_tm(t);
}

修改ds1307_set_time函数:

static int ds1307_set_time(struct device *dev, struct rtc_time *t)
{struct ds1307  *ds1307 = dev_get_drvdata(dev);int     result;int      tmp;u8      *buf = ds1307->regs;dev_dbg(dev, "%s secs=%d, mins=%d, ""hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n","write", t->tm_sec, t->tm_min,t->tm_hour, t->tm_mday,t->tm_mon, t->tm_year, t->tm_wday);buf[DS1307_REG_SECS] = bin2bcd(t->tm_sec);buf[DS1307_REG_MIN] = bin2bcd(t->tm_min);buf[DS1307_REG_HOUR] = bin2bcd(t->tm_hour);buf[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);buf[DS1307_REG_MDAY] = bin2bcd(t->tm_mday);buf[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1);/* assume 20YY not 19YY */tmp = t->tm_year - 100;buf[DS1307_REG_YEAR] = bin2bcd(tmp);switch (ds1307->type) {case ds_1337:case ds_1339:case ds_3231:buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;break;case ds_1340:buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN| DS1340_BIT_CENTURY;break;case mcp794xx:/** these bits were cleared when preparing the date/time* values and need to be set again before writing the* buffer out to the device.*/buf[DS1307_REG_SECS] |= MCP794XX_BIT_ST;buf[DS1307_REG_WDAY] |= MCP794XX_BIT_VBATEN;break;/*add ht1382*/case ht_1382:buf[HT1382_REG_WDAY] = bin2bcd(t->tm_wday + 1);buf[HT1382_REG_MDAY] = bin2bcd(t->tm_mday);buf[HT1382_REG_MONTH] = bin2bcd(t->tm_mon + 1);break;/*add end*/default:break;}dev_dbg(dev, "%s: %7ph\n", "write", buf);result = ds1307->write_block_data(ds1307->client,ds1307->offset, 7, buf);if (result < 0) {dev_err(dev, "%s error %d\n", "write", result);return result;}return 0;
}

修改这两个函数关于月,日,星期的寄存器内容写入即可。

在rtc ds1307的驱动中增加rtc ht1382芯片驱动相关推荐

  1. openwrt配置内核驱动_openwrt 增加RTC(MCP7940 I2C总线)驱动详解

    标签: 一.硬件平台 1.1 控制器:MT7620(A9内核) 1.2 RTC芯片:MCP7940(I2C总线) 二.软件平台 2.1.开发环境:Ubuntu12.04 2.2.软件版本:openwr ...

  2. RK3399驱动开发 | 04 - WK2124串口芯片驱动浅析

    一.驱动挂载与卸载 加载模块之后,查看完整的系统日志: 1. 模块加载与卸载 WK2124使用spi总线通信,所以在模块加载的时候向内核注册spi驱动. 2. 驱动挂载与卸载 可以看到spi驱动兼容性 ...

  3. linux按键驱动中的结构体,linux 驱动之input子系统(gpio-keys)实现

    1.概述 Gpio-keys 是基于input子系统实现的一个通用按键驱动,该驱动也符合linux驱动实现模型,即driver和device分离模型.一般按键驱动,都是基于gpio-keys进行开发的 ...

  4. spi转串口 linux驱动,RT_Thread WK2124 SPI转串口芯片驱动软件包

    WK2124 软件包 1 介绍 WK2124 软件包是为WK2124 SPI转四串口扩展芯片而开发的RT-Thread驱动包.通过RT-Thread SPI 设备和RT-Thread UART 设备驱 ...

  5. RK3399驱动开发 | 03 - WK2124串口芯片驱动调试

    最近在调试过程中发现WK2124这个串口扩展芯片比较有意思,写篇文章来记录一下调试心得. 一.WK2124 1. 概述 WK2124是SPI接口的4通道UART器件,实现了SPI扩展4个串口的功能. ...

  6. Linux驱动开发-编写PCF8591(ADC)芯片驱动

    1. PCF8591介绍 PCF8591是一个IIC总线接口的ADC/DAC转换芯片,功能比较强大,这篇文章就介绍在Linux系统里如何编写一个PCF8591的驱动,完成ADC数据采集,DAC数据输出 ...

  7. linux驱动中printk的使用注意事项

    今天在按键驱动中增加printk(KERN_INFO "gpio_keys_gpio_isr()\n");在驱动加载阶段可以输出调试信息,但驱动加载起来后的信息,在串口端看不到输出 ...

  8. linux驱动开发5之字符设备驱动新接口

    1.新接口与老接口 1)老接口:register_chrdev static inline int register_chrdev(unsigned int major, const char *na ...

  9. imx6 linux 时钟,迅为-iMX6开发板-驱动-实时时钟RTC以及Linux-c测试例程

    当Linux开发者谈论一个实时时钟,他们通常指的是某种能记录墙上时间,并且有备用电 池,以至于在系统关机的时候仍然可以工作的器件. Linux 有两个系列广泛兼容的用户空间 RTC 设备节点: /de ...

最新文章

  1. 网络慢是带宽不足?优化网络带宽的5个小窍门
  2. 我才知道wordpress还有com和org的区别呢
  3. 打通NTFS权限 文件共享各取所需
  4. php标准库string,PHP中的一些标准库
  5. kafka redis vs 发布订阅_发布订阅的消息系统 Kafka的深度解析
  6. 关于 安利商品“欺诈”案
  7. 在Win10 LTSC 2019上安装和卸载linux子系统
  8. 根据pid查端口_PID控制原理:看完这几个故事你就明白了
  9. 时间复杂度与空间复杂度
  10. android 高仿网易,Android项目实战教程之高仿网易云音乐启动页实例代码
  11. 用微信网页版阅读文章
  12. ppt复制切片器_ppt中制作动态图表,并不难,使用powerbi三步搞定
  13. 日程安排工具Calendso
  14. 【好文分享】提升早晨工作效率的小tips
  15. Ubantu基础指令大集合
  16. Win10 Bash搭建嵌入式Qt开发平台
  17. 《树莓派开发笔记 - 第1部分 基础篇》第7章 树莓派变身路由器
  18. 两台windows电脑互相备份
  19. 让div中的p标签文字垂直居中的方法
  20. 怎样使表格中的数字自动计算机,#怎样让一个表格自动加或乘#如何使excel表格里多个数同时除以1000?...

热门文章

  1. Python3-word文档操作(二):利用python获取word文档的内容
  2. Codeforces #208 div2前两题及思维风暴
  3. java wirter_Java FileWriter类 - Java 教程 - 自强学堂
  4. AE基础教程第一阶段——09快速预览
  5. Mongodb 数据库基本操作语句,结合 Node.js + express + mongoose (实现增、删、改、查,批量增加、修改等,创建临时表,多表查询......)
  6. 2023计算机毕业设计题目选题经验
  7. 为什么安监控需要公网ip_三种方法告诉你项目超过255个摄像机怎么设置IP?
  8. 难度大幅上涨!初试公共/专业课都改了!东南大学软件学院考研
  9. 针对直播痛点的关键技术解析——首帧秒开、清晰度、流畅度
  10. 小型服务器的容量能无限扩充吗,揭秘1U服务器无限扩充能力