[Armadeus-commitlog] armadeus branch, master, updated. armadeus-5.2-50-g9511ad2
Brought to you by:
sszy
|
From: Fabien M <fa...@us...> - 2012-11-16 17:12:30
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "armadeus".
The branch, master has been updated
via 9511ad23cdd6f7fe97a42c0151f8cce19895015e (commit)
from 867c29554202c221217894ecf18d9f5efe8d8f32 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 9511ad23cdd6f7fe97a42c0151f8cce19895015e
Author: Fabien Marteau <fab...@ar...>
Date: Fri Nov 16 18:04:57 2012 +0100
[kernel] Adding mcp7940x rtc driver
-----------------------------------------------------------------------
Summary of changes:
.../armadeus/apf51/apf51-linux-2.6.38.config | 1 +
.../450-armadeus-add_mcp7940x_rtc_driver.patch | 357 ++++++++++++++++++++
2 files changed, 358 insertions(+), 0 deletions(-)
create mode 100644 patches/linux/2.6.38/450-armadeus-add_mcp7940x_rtc_driver.patch
diff --git a/buildroot/target/device/armadeus/apf51/apf51-linux-2.6.38.config b/buildroot/target/device/armadeus/apf51/apf51-linux-2.6.38.config
index bb22dc4..ab62206 100644
--- a/buildroot/target/device/armadeus/apf51/apf51-linux-2.6.38.config
+++ b/buildroot/target/device/armadeus/apf51/apf51-linux-2.6.38.config
@@ -249,6 +249,7 @@ CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MCP7940X is not set
CONFIG_RTC_MXC=y
CONFIG_RTC_DRV_WM831X=y
CONFIG_STAGING=y
diff --git a/patches/linux/2.6.38/450-armadeus-add_mcp7940x_rtc_driver.patch b/patches/linux/2.6.38/450-armadeus-add_mcp7940x_rtc_driver.patch
new file mode 100644
index 0000000..d3ac48d
--- /dev/null
+++ b/patches/linux/2.6.38/450-armadeus-add_mcp7940x_rtc_driver.patch
@@ -0,0 +1,357 @@
+Add mcp79400 Linux driver
+
+Signed-off-by: Fabien Marteau <fab...@ar...>
+
+---
+
+Index: linux-2.6.38.8/drivers/rtc/Kconfig
+===================================================================
+--- linux-2.6.38.8.orig/drivers/rtc/Kconfig 2012-11-16 17:52:01.000000000 +0100
++++ linux-2.6.38.8/drivers/rtc/Kconfig 2012-11-16 17:54:51.000000000 +0100
+@@ -282,6 +282,17 @@
+ If you say Y here you will get support for the
+ watchdog timer in the ST M41T60 and M41T80 RTC chips series.
+
++config RTC_DRV_MCP7940X
++ tristate "Microchip MCP7940X"
++ depends on RTC_CLASS && I2C
++ help
++ If you say yes here you get support for Microchip
++ MCP7940x real-time clock chips.
++ The alarm functionality is not supported.
++
++ This driver can also be built as a module. If so, the module
++ will be called rtc-mcp7940x.
++
+ config RTC_DRV_BQ32K
+ tristate "TI BQ32000"
+ help
+Index: linux-2.6.38.8/drivers/rtc/Makefile
+===================================================================
+--- linux-2.6.38.8.orig/drivers/rtc/Makefile 2012-11-16 17:51:56.000000000 +0100
++++ linux-2.6.38.8/drivers/rtc/Makefile 2012-11-16 17:52:28.000000000 +0100
+@@ -64,6 +64,7 @@
+ obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o
+ obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
+ obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o
++obj-$(CONFIG_RTC_DRV_MCP7940X) += rtc-mcp7940x.o
+ obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
+ obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o
+ obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
+Index: linux-2.6.38.8/drivers/rtc/rtc-mcp7940x.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.38.8/drivers/rtc/rtc-mcp7940x.c 2012-11-16 17:54:34.000000000 +0100
+@@ -0,0 +1,312 @@
++/*
++ * RTC client/driver for the Microchip MCP7940x Real-Time Clock over I2C
++ *
++ * Based on code by Scott Wood <sco...@fr...>
++ * which was based on code by Randy Vinson <rv...@mv...>,
++ * which was based on the m41t00.c by Mark Greer <mg...@mv...>.
++ *
++ * Copyright (C) 2012 Armadeus Systems
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++/*
++ * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
++ * recommened in .../Documentation/i2c/writing-clients section
++ * "Sending and receiving", using SMBus level communication is preferred.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/rtc.h>
++#include <linux/bcd.h>
++#include <linux/slab.h>
++
++/* Time of Day */
++#define MCP7940X_REG_TD_SECONDS 0x00
++#define MCP7940X_REG_TD_MINUTES 0x01
++#define MCP7940X_REG_TD_HOURS 0x02
++#define MCP7940X_REG_TD_DAY 0x03
++#define MCP7940X_REG_TD_DATE 0x04
++#define MCP7940X_REG_TD_MONTH 0x05
++#define MCP7940X_REG_TD_YEAR 0x06
++/* Controls */
++#define MCP7940X_REG_CONTROL 0x07
++#define MCP7940X_REG_CALIBRATION 0x08
++#define MCP7940X_REG_UNLOCK_ID 0x08
++/* Alarm 0 */
++#define MCP7940X_REG_ALRM0_SECONDS 0x0A
++#define MCP7940X_REG_ALRM0_MINUTES 0x0B
++#define MCP7940X_REG_ALRM0_HOURS 0x0C
++#define MCP7940X_REG_ALRM0_DAY 0x0D
++#define MCP7940X_REG_ALRM0_DATE 0x0E
++#define MCP7940X_REG_ALRM0_MONTH 0x0F
++/* Alarm 1 */
++#define MCP7940X_REG_ALRM1_SECONDS 0x11
++#define MCP7940X_REG_ALRM1_MINUTES 0x12
++#define MCP7940X_REG_ALRM1_HOURS 0x13
++#define MCP7940X_REG_ALRM1_DAY 0x14
++#define MCP7940X_REG_ALRM1_DATE 0x15
++#define MCP7940X_REG_ALRM1_MONTH 0x16
++/* Timestamp 0 */
++#define MCP7940X_REG_TS0_MINUTES 0x18
++#define MCP7940X_REG_TS0_HOURS 0x19
++#define MCP7940X_REG_TS0_DATE 0x1A
++#define MCP7940X_REG_TS0_MONTH 0x1B
++/* Timestamp 1 */
++#define MCP7940X_REG_TS1_MINUTES 0x1C
++#define MCP7940X_REG_TS1_HOURS 0x1D
++#define MCP7940X_REG_TS1_DATE 0x1E
++#define MCP7940X_REG_TS1_MONTH 0x1F
++
++
++/* bits definitions */
++#define MCP7940X_START_BITS 0x80
++#define MCP7940X_24H_BITS 0x40
++#define MCP7940X_VBATEN 0x08
++
++static const struct i2c_device_id mcp7940x_id[] = {
++ { "mcp79400", 0 }, /* no unique ID */
++ { "mcp79401", 1 }, /* EUI-48 */
++ { "mcp79402", 2 }, /* EUI-64 */
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, mcp7940x_id);
++
++struct mcp7940x {
++ struct i2c_client *client;
++ struct rtc_device *rtc;
++ int exiting;
++};
++
++static struct i2c_driver mcp7940x_driver;
++
++//struct rtc_time {
++// int tm_sec;
++// int tm_min;
++// int tm_hour;
++// int tm_mday;
++// int tm_mon;
++// int tm_year;
++// int tm_wday;
++// int tm_yday;
++// int tm_isdst;
++//};
++
++static int mcp7940x_read_time(struct device *dev, struct rtc_time *time)
++{
++ struct i2c_client *client = to_i2c_client(dev);
++ int ret;
++
++ ret = i2c_smbus_read_byte_data(client, MCP7940X_REG_TD_SECONDS);
++ if (ret < 0)
++ return ret;
++ time->tm_sec = ((ret&0x70)>>4)*10 + (ret&0x0F);
++
++ ret = i2c_smbus_read_byte_data(client, MCP7940X_REG_TD_MINUTES);
++ if (ret < 0)
++ return ret;
++ time->tm_min = ((ret&0x70)>>4)*10 + (ret&0x0F);
++
++ ret = i2c_smbus_read_byte_data(client, MCP7940X_REG_TD_HOURS);
++ if (ret < 0)
++ return ret;
++ time->tm_hour = ((ret&0x30)>>4)*10 + (ret&0x0F);
++
++ ret = i2c_smbus_read_byte_data(client, MCP7940X_REG_TD_DATE);
++ if (ret < 0)
++ return ret;
++ time->tm_mday = ((ret&0x30)>>4)*10 + (ret&0x0F);
++
++ ret = i2c_smbus_read_byte_data(client, MCP7940X_REG_TD_MONTH);
++ if (ret < 0)
++ return ret;
++ time->tm_mon = (((ret&0x10)>>4)*10 + (ret&0x0F)) - 1;
++
++ ret = i2c_smbus_read_byte_data(client, MCP7940X_REG_TD_YEAR);
++ if (ret < 0)
++ return ret;
++ time->tm_year = ((((ret&0xF0)>>4)*10 + (ret&0x0F))) + 100;
++
++ return 0;
++}
++
++static int mcp7940x_set_time(struct device *dev, struct rtc_time *time)
++{
++ struct i2c_client *client = to_i2c_client(dev);
++ int ret;
++ int value;
++
++ value = ((((time->tm_sec/10)&0x07)<<4)|(time->tm_sec % 10))|
++ MCP7940X_START_BITS;
++ ret = i2c_smbus_write_byte_data(client,
++ MCP7940X_REG_TD_SECONDS,
++ value);
++ if (ret < 0)
++ return ret;
++
++ value = (((time->tm_min/10)&0x07)<<4)|(time->tm_min % 10);
++ ret = i2c_smbus_write_byte_data(client,
++ MCP7940X_REG_TD_MINUTES,
++ value);
++ if (ret < 0)
++ return ret;
++
++ value = ((((time->tm_hour/10)&0x03)<<4)|(time->tm_hour % 10));
++ ret = i2c_smbus_write_byte_data(client,
++ MCP7940X_REG_TD_HOURS,
++ value);
++ if (ret < 0)
++ return ret;
++
++ value = (((time->tm_mday/10)&0x03)<<4)|(time->tm_mday % 10);
++ ret = i2c_smbus_write_byte_data(client,
++ MCP7940X_REG_TD_DATE,
++ value);
++ if (ret < 0)
++ return ret;
++
++ value = ((((time->tm_mon+1)/10)&0x01)<<4)|((time->tm_mon+1) % 10);
++ ret = i2c_smbus_write_byte_data(client,
++ MCP7940X_REG_TD_MONTH,
++ value);
++ if (ret < 0)
++ return ret;
++
++ value = ((((time->tm_year-100)/10)&0x0F)<<4)|((time->tm_year-100) % 10);
++ ret = i2c_smbus_write_byte_data(client,
++ MCP7940X_REG_TD_YEAR,
++ value);
++ if (ret < 0)
++ return ret;
++
++ return 0;
++}
++
++static const struct rtc_class_ops mcp7940x_rtc_ops = {
++ .read_time = mcp7940x_read_time,
++ .set_time = mcp7940x_set_time,
++};
++
++static int mcp7940x_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct mcp7940x *mcp7940x;
++ int ret;
++
++ mcp7940x = kzalloc(sizeof(struct mcp7940x), GFP_KERNEL);
++ if (!mcp7940x)
++ return -ENOMEM;
++
++ mcp7940x->client = client;
++ i2c_set_clientdata(client, mcp7940x);
++
++ ret = i2c_smbus_read_byte_data(mcp7940x->client, MCP7940X_REG_TD_HOURS);
++ if (ret < 0)
++ goto out_free;
++
++ /* set rtc to 24h format */
++ if ((ret & MCP7940X_24H_BITS)) {
++ ret = i2c_smbus_write_byte_data(mcp7940x->client,
++ MCP7940X_REG_TD_HOURS,
++ (u8)(ret & ~MCP7940X_24H_BITS));
++ if(ret < 0)
++ goto out_free;
++ }
++
++ ret = i2c_smbus_read_byte_data(mcp7940x->client, MCP7940X_REG_TD_DAY);
++ if (ret < 0)
++ goto out_free;
++ /* Use external baterie if Vcc fails */
++ if (!(ret & MCP7940X_VBATEN)) {
++ ret = i2c_smbus_write_byte_data(mcp7940x->client,
++ MCP7940X_REG_TD_DAY,
++ (u8)(ret | MCP7940X_VBATEN));
++ if(ret < 0)
++ goto out_free;
++ }
++
++ ret = i2c_smbus_read_byte_data(mcp7940x->client, MCP7940X_REG_TD_SECONDS);
++ if (ret < 0)
++ goto out_free;
++
++ /* If time counter not launched, launch it */
++ if (!(ret & MCP7940X_START_BITS)) {
++ ret = i2c_smbus_write_byte_data(mcp7940x->client,
++ MCP7940X_REG_TD_SECONDS,
++ (u8)(ret | MCP7940X_START_BITS));
++ if(ret < 0)
++ goto out_free;
++
++ }
++
++ mcp7940x->rtc = rtc_device_register(client->name, &client->dev,
++ &mcp7940x_rtc_ops, THIS_MODULE);
++ if (IS_ERR(mcp7940x->rtc)) {
++ ret = PTR_ERR(mcp7940x->rtc);
++ dev_err(&client->dev, "unable to register the class device\n");
++ goto out_free;
++ }
++
++ return 0;
++
++out_free:
++ kfree(mcp7940x);
++ return ret;
++}
++
++static int __devexit mcp7940x_remove(struct i2c_client *client)
++{
++ struct mcp7940x *mcp7940x = i2c_get_clientdata(client);
++
++ rtc_device_unregister(mcp7940x->rtc);
++ kfree(mcp7940x);
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int mcp7940x_suspend(struct i2c_client *client, pm_message_t state)
++{
++ return 0;
++}
++
++static int mcp7940x_resume(struct i2c_client *client)
++{
++ return 0;
++}
++#else
++#define mcp7940x_suspend NULL
++#define mcp7940x_resume NULL
++#endif
++
++static struct i2c_driver mcp7940x_driver = {
++ .driver = {
++ .name = "rtc-mcp7940x",
++ .owner = THIS_MODULE,
++ },
++ .probe = mcp7940x_probe,
++ .suspend = mcp7940x_suspend,
++ .resume = mcp7940x_resume,
++ .remove = __devexit_p(mcp7940x_remove),
++ .id_table = mcp7940x_id,
++};
++
++static int __init mcp7940x_init(void)
++{
++ return i2c_add_driver(&mcp7940x_driver);
++}
++
++static void __exit mcp7940x_exit(void)
++{
++ i2c_del_driver(&mcp7940x_driver);
++}
++
++module_init(mcp7940x_init);
++module_exit(mcp7940x_exit);
++
++MODULE_AUTHOR("Fabien Marteau <fab...@ar...>");
++MODULE_DESCRIPTION("Microchip mcp7940x RTC Driver");
++MODULE_LICENSE("GPL");
hooks/post-receive
--
armadeus
|