[RK3288][Android6.0] RTC模块RX8010SJ驱动添加及改动

在Rockchip RK3288平台运行Android 6.0系统,内核3.10.92时,针对RTC模块RX8010SJ驱动进行修复和改动。原驱动存在错误,包括寄存器地址错误、上电初始化问题以及alarm功能未启用。通过修正这些问题,实现了RTC的正常工作,并确保了时间读写及alarm功能的正确注册。
摘要由CSDN通过智能技术生成

Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92

在网上的其他branch上找到一份RX8010SJ的驱动,但是有点问题,先贴代码,再说明修改部分。

设备部分:

比较简单,确定I2C端口以及设备地址就行。
&i2c1 {
status = “okay”;
rx8010: rx8010@32 {
compatible = “epson,rx8010”;
reg = <0x32>;
status = “okay”;
};
};

驱动部分:

此驱动已经可以读写时间,alarm部分因为没有需求,所以硬件没接,也未做测试。

/*
 * Driver for the Epson RTC module RX-8010 SJ
 *
 * Copyright(C) Timesys Corporation 2015
 * Copyright(C) General Electric Company 2015
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */

#include <linux/bcd.h>
#include <linux/bitops.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/rtc.h>

#define RX8010_SEC     0x10
#define RX8010_MIN     0x11
#define RX8010_HOUR    0x12
#define RX8010_WDAY    0x13
#define RX8010_MDAY    0x14
#define RX8010_MONTH   0x15
#define RX8010_YEAR    0x16
#define RX8010_YEAR    0x16
#define RX8010_RESV17  0x17
#define RX8010_ALMIN   0x18
#define RX8010_ALHOUR  0x19
#define RX8010_ALWDAY  0x1A
#define RX8010_TCOUNT0 0x1B
#define RX8010_TCOUNT1 0x1C
#define RX8010_EXT     0x1D
#define RX8010_FLAG    0x1E
#define RX8010_CTRL    0x1F
/* 0x20 to 0x2F are user registers */
#define RX8010_RESV30  0x30
#define RX8010_RESV31  0x31
#define RX8010_IRQ     0x32

#define RX8010_EXT_WADA  BIT(3)

#define RX8010_FLAG_VLF  BIT(1)
#define RX8010_FLAG_AF   BIT(3)
#define RX8010_FLAG_TF   BIT(4)
#define RX8010_FLAG_UF   BIT(5)

#define RX8010_CTRL_AIE  BIT(3)
#define RX8010_CTRL_UIE  BIT(5)
#define RX8010_CTRL_STOP BIT(6)
#define RX8010_CTRL_TEST BIT(7)

#define RX8010_ALARM_AE  BIT(7)

static const struct i2c_device_id rx8010_id[] = {
    { "rx8010", 0 },
    { }
};
MODULE_DEVICE_TABLE(i2c, rx8010_id);

static const struct of_device_id rx8010_of_match[] = {
    { .compatible = "epson,rx8010" },
    { }
};
MODULE_DEVICE_TABLE(of, rx8010_of_match);

struct rx8010_data {
    struct i2c_client *client;
    struct rtc_device *rtc;
    u8 ctrlreg;
};

static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id)
{
    struct i2c_client *client = dev_id;
    struct rx8010_data *rx8010 = i2c_get_clientdata(client);
    int flagreg;

    mutex_lock(&rx8010->rtc->ops_lock);

    flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG);

    if (flagreg <= 0) {
        mutex_unlock(&rx8010->rtc->ops_lock);
        return IRQ_NONE;
    }

    if (flagreg & RX8010_FLAG_VLF)
        dev_warn(&client->dev, "Frequency stop detected\n");

    if (flagreg & RX8010_FLAG_TF) {
        flagreg &= ~RX8010_FLAG_TF;
        rtc_update_irq(rx8010->rtc, 1, RTC_PF | RTC_IRQF);
    }

    if (flagreg & RX8010_FLAG_AF) {
        flagreg &= ~RX8010_FLAG_AF;
        rtc_update_irq(rx8010->rtc, 1, RTC_AF | RTC_IRQF);
    }

    if (flagreg & RX8010_FLAG_UF) {
        flagreg &= ~RX8010_FLAG_UF;
        rtc_update_irq(rx8010->rtc, 1, RTC_UF | RTC_IRQF);
    }

    i2c_smbus_write_byte_data(client, RX8010_FLAG, flagreg);

    mutex_unlock(&rx8010->rtc->ops_lock);
    return IRQ_HANDLED;
}

static int rx8010_get_time(struct device *dev, struct rtc_time *dt)
{
    struct rx8010_data *rx8010 = dev_get_drvdata(dev);
    u8 date[7];
    int flagreg;
    int err;

    flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG);
    if (flagreg < 0)
        return flagreg;

    if (flagreg & RX8010_FLAG_VLF) {
        dev_warn(dev, "Frequency stop detected\n");
        return -EINVAL;
    }

    err = i2c_smbus_read_i2c_block_data(rx8010->client</
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值