From: Tolunay Orkun <listmember@orkun.us>
To: Sam Song <samlinuxppc@yahoo.com.cn>
Cc: linuxppc-embedded@ozlabs.org
Subject: Re: Available user-level tool for I2C device?
Date: Thu, 29 Sep 2005 13:59:26 -0500 [thread overview]
Message-ID: <433C398E.30408@orkun.us> (raw)
In-Reply-To: <20050929123535.66570.qmail@web15803.mail.cnb.yahoo.com>
[-- Attachment #1: Type: text/plain, Size: 530 bytes --]
Sam,
Sam Song wrote:
> Hi all,
>
> I'd like to ask whether there is user-level utility
> for I2C device registers access like lspci/setpci for
> PCI device?
>
> I have a RTC chip DS1337 on a 8248 target. It can
> work right in u-boot and linux. If no similar utility,
> I will switch to change hwclock.c in busybox to make
> it. Any idea?
>
> Thanks in advance,
>
> Sam
I've a hwclock.c implementation for DS1307/DS1338. I do not know how
close DS1337 was but it should not be too difficult to adapt.
Best regards,
Tolunay
[-- Attachment #2: hwclock_ds1307.c --]
[-- Type: text/x-csrc, Size: 6803 bytes --]
/*
* Mini hwclock implementation suitable for DS1307/DS1338 RTC chips
*
* Copyright (C) 2004 NextIO Inc. - Tolunay Orkun <torkun@nextio.com>
*
* Based on GPL licensed code from Busybox and U-boot projects
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <sys/ioctl.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <getopt.h>
#include <fcntl.h>
#include <stdio.h>
#include <libgen.h>
#include <stdlib.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define DS1307_ADDR 0x68
struct i2c_ioctl_rdwr_data {
struct i2c_msg *msgs;
int nmsgs;
};
int i2c_xfer(int addr, char *wbuf, int wcount, char *rbuf, int rcount)
{
int fd, i;
int val, nmsgs;
struct i2c_msg msg[2];
struct i2c_ioctl_rdwr_data ioctl_rdwr_data;
memset(msg, 0, sizeof(msg));
memset(&ioctl_rdwr_data, 0, sizeof(ioctl_rdwr_data));
nmsgs = 0;
if (wcount > 0) {
msg[nmsgs].addr = addr;
msg[nmsgs].flags = 0;
msg[nmsgs].len = wcount;
msg[nmsgs].buf = wbuf;
nmsgs++;
}
if (rcount > 0) {
msg[nmsgs].addr = addr;
msg[nmsgs].flags = I2C_M_RD;
msg[nmsgs].len = rcount;
msg[nmsgs].buf = rbuf;
nmsgs++;
}
ioctl_rdwr_data.msgs = msg;
ioctl_rdwr_data.nmsgs = nmsgs;
#ifdef DEBUG
if (wcount > 0) {
printf("Writing i2c...\n");
printf("Addr : %3d (0x%02x)\n", addr, addr);
printf("Count: %3d (0x%02x)\n", wcount, wcount);
printf("Data :\n");
for (i = 0; i < wcount; i++) {
val = wbuf[i];
printf("%3d (0x%02x) = %3d (0x%02x)\n", i, i, val, val);
}
printf("\n");
}
if (rcount > 0) {
printf("Reading i2c...\n");
printf("Addr : %3d (0x%02x)\n", addr, addr);
printf("Count: %3d (0x%02x)\n", rcount, rcount);
}
#endif
fd = open("/dev/i2c0", O_RDWR);
if (fd < 0) {
fd = open("/dev/i2c/0", O_RDWR);
if (fd < 0) {
printf("Can't open i2c\n");
return 1;
}
}
if (ioctl(fd, I2C_RDWR, &ioctl_rdwr_data) < 0) {
printf("I2C I/O Error\n");
close(fd);
return 2;
}
#ifdef DEBUG
if (rcount > 0) {
printf("Data :\n");
for (i = 0; i < rcount; i++) {
val = rbuf[i];
printf("%3d (0x%02x) = %3d (0x%02x)\n", i, i, val, val);
}
printf("\n");
}
#endif
close(fd);
return 0;
}
unsigned int bcd2bin(unsigned char n)
{
return ((((n >> 4) & 0x0f) * 10) + (n & 0x0f));
}
unsigned char bin2bcd(unsigned int n)
{
return (((n / 10) << 4) | (n % 10));
}
time_t read_rtc(int utc)
{
char reg = 0; /* register start address for transfer */
char buf[8];
struct tm tm;
char *oldtz = NULL;
time_t t = 0;
if (i2c_xfer(DS1307_ADDR, ®, sizeof(reg), buf, sizeof(buf)) != 0)
return -1;
memset(&tm, 0, sizeof(struct tm));
tm.tm_sec = bcd2bin(buf[0] & 0x7f);
tm.tm_min = bcd2bin(buf[1] & 0x7f);
tm.tm_hour = bcd2bin(buf[2] & 0x3f);
tm.tm_wday = bcd2bin(buf[3] & 0x07) - 1;
tm.tm_mday = bcd2bin(buf[4] & 0x3f);
tm.tm_mon = bcd2bin(buf[5] & 0x1f) - 1;
tm.tm_year = bcd2bin(buf[6]) + 100;
tm.tm_isdst = -1; /* unknown */
if (utc) {
oldtz = getenv("TZ");
setenv("TZ", "UTC 0", 1);
tzset();
}
t = mktime(&tm);
if (utc) {
if (oldtz)
setenv("TZ", oldtz, 1);
else
unsetenv("TZ");
tzset();
}
return t;
}
int write_rtc(time_t t, int utc)
{
char buf[8];
struct tm tm;
tm = *(utc ? gmtime(&t) : localtime(&t));
buf[0] = 0; /* register start address for transfer */
buf[1] = bin2bcd(tm.tm_sec);
buf[2] = bin2bcd(tm.tm_min);
buf[3] = bin2bcd(tm.tm_hour);
buf[4] = bin2bcd(tm.tm_wday + 1);
buf[5] = bin2bcd(tm.tm_mday);
buf[6] = bin2bcd(tm.tm_mon + 1);
buf[7] = bin2bcd(tm.tm_year - 100);
if (i2c_xfer(DS1307_ADDR, buf, sizeof(buf), NULL, 0) != 0)
return -1;
return 0;
}
int show_clock(int utc)
{
time_t t;
char buffer[64];
char *p;
int len;
buffer[0] = '\0';
t = read_rtc(utc);
p = ctime(&t);
if (p) {
len = strlen(p) - 1; /* strip newline */
if (len >= sizeof(buffer))
len = sizeof(buffer) - 1;
memcpy(buffer, p, len);
buffer[len] = '\0';
}
printf("%s 0.000000 seconds\n", buffer);
return 0;
}
int to_sys_clock(int utc)
{
struct timeval tv;
memset(&tv, 0, sizeof(tv));
tv.tv_sec = read_rtc(utc);
return settimeofday(&tv, NULL);
}
int from_sys_clock(int utc)
{
struct timeval tv;
memset(&tv, 0, sizeof(tv));
gettimeofday(&tv, NULL);
return write_rtc(tv.tv_sec, utc);
}
void show_usage(char *progname)
{
char buf[64];
strncpy(buf, progname, sizeof(buf));
buf[sizeof(buf) - 1] = '\0';
basename(buf);
printf("%s - query and set the hardware clock (DS1307/1338 RTC)\n\n", buf);
printf("Usage: %s [options...]\n\n", buf);
printf("Options:\n");
printf("\t-r, --show\tread hardware clock and print result\n");
printf("\t-s, --hctosys\tset the system time from the hardware clock\n");
printf("\t-w, --systohc\tset the hardware clock to the current system time\n\n");
printf("\t-u, --utc\tthe hardware clock is kept in universal time\n");
printf("\t-l, --localtime\tthe hardware clock is kept in local time\n\n");
exit(-1);
}
int main(int argc, char *argv[])
{
int opt_help = 0;
int opt_localtime = 0;
int opt_utc = 0;
int func_show = 0;
int func_hctosys = 0;
int func_systohc = 0;
int func_count;
int utc;
int c;
static struct option long_options[] = {
{ "show", 0, 0, 'r' },
{ "hctosys", 0, 0, 's' },
{ "systohc", 0, 0, 'w' },
{ "localtime", 0, 0, 'l' },
{ "utc", 0, 0, 'u' },
{ "help", 0, 0, '?' },
{ 0, 0, 0, 0 }
};
int opt_idx = 0;
while (1) {
c = getopt_long(argc, argv, "rswlu?h", long_options, &opt_idx);
if (c == -1)
break;
switch (c) {
case 'r':
func_show = 1;
break;
case 's':
func_hctosys = 1;
break;
case 'w':
func_systohc = 1;
break;
case 'l':
opt_localtime = 1;
break;
case 'u':
opt_utc = 1;
break;
default:
opt_help = 1;
break;
}
}
func_count = func_show + func_hctosys + func_systohc;
if (func_count > 1)
show_usage(argv[0]);
if (opt_localtime && opt_utc)
show_usage(argv[0]);
if (opt_help)
show_usage(argv[0]);
if (func_hctosys)
return to_sys_clock(opt_utc);
else if (func_systohc)
return from_sys_clock(opt_utc);
else
return show_clock(opt_utc);
return 0;
}
/* ex: set sw=4 ts=4: */
next prev parent reply other threads:[~2005-09-29 18:59 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-09-29 12:35 Available user-level tool for I2C device? Sam Song
2005-09-29 16:57 ` Eugene Surovegin
2005-10-01 3:50 ` Sam Song
2005-09-29 18:59 ` Tolunay Orkun [this message]
2005-10-01 3:58 ` Sam Song
2005-10-02 13:58 ` Yuli Barcohen
2005-10-05 3:33 ` Sam Song
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=433C398E.30408@orkun.us \
--to=listmember@orkun.us \
--cc=linuxppc-embedded@ozlabs.org \
--cc=samlinuxppc@yahoo.com.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.