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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).