Commit 3df60e41 authored by Albert Cranford's avatar Albert Cranford Committed by Linus Torvalds

[PATCH] i2c updates 4/4

Please apply the four of four tested patches that update
2.5.31 with these I2C changes:
 o Support for SMBus 2.0 PEC Packet Error Checking
 o New adapter-i2c-frodo for SA 1110 board
 o New adapter-i2c-rpx for embeded MPC8XX
 o Replace depreciated cli()&sti() with spin_{un}lock_irq()
 o Updated documentation
parent 9bc9da2d
......@@ -87,7 +87,12 @@ ioctl(file,I2C_SLAVE,long addr)
ioctl(file,I2C_TENBIT,long select)
Selects ten bit addresses if select not equals 0, selects normal 7 bit
addresses if select equals 0.
addresses if select equals 0. Default 0.
ioctl(file,I2C_PEC,long select)
Selects SMBus PEC (packet error checking) generation and verification
if select not equals 0, disables if select equals 0. Default 0.
Used only for SMBus transactions.
ioctl(file,I2C_FUNCS,unsigned long *funcs)
Gets the adapter functionality and puts it in *funcs.
......
I2C Conversion Guide for I2C-old to the current I2C API
July 2002
For Linux Kernel v2.5.x
Frank Davis <fdavis@si.rr.com>
-------------------------------------------------------
There exists several kernel drivers that are using an old version of the I2C
API. These drivers need to be converted to the current (kernel 2.5.x) version.
The following document provides a guideline to make the appropriate changes to
the affected drivers. There maybe slight modifications to this guide that are
specific to the driver you are working on. If you see {driver_name}, replace
that with the respective name of the driver, such as saa7110.c , {driver_name}
= saa7110.
-------------------------------------------------------
Step 1: Include the right header file
Perform the following change within the driver
#include <linux/i2c-old.h> --> #include <linux/i2c.h>
Step 2: Add and set the i2c modes
Add the following code near the top of the driver
static unsigned short normal_i2c[] = {34>>1, I2C_CLIENT_END };
static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
static unsigned short probe[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
static unsigned short probe_range[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
static unsigned short ignore[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
static struct i2c_client_address_data addr_data = {
normal_i2c , normal_i2c_range,
probe , probe_range,
ignore , ignore_range,
force
};
static struct i2c_client client_template;
Step 3: Modify the driver info struct
Within the struct for the driver , such as struct {driver_name} , make the
following change ,
struct i2c_bus *bus --> struct i2c_client *client
Make changes where this change affects references within the file.
Add a semaphore to the driver struct (as above)
struct semaphore lock
Step 5: Remove specific read and write functions
Remove the driver specific write and read functions, usually in the form:
{driver_name}_write , {driver_name}_read , {driver_name}_write_block , etc.
Step 6: Update the write and read functions for the current I2C API
Replace all references of {driver_name}_write with i2c_smbus_write_byte_data
Replace all references of {driver_name}_read with i2c_smbus_read_byte_data or
i2c_smbus_read_byte , depending on args passed in.
** Ensure that these functions pass in the i2c_client *client , NOT the
decoder/encoder that was passed in the driver specific write and read
functions.
Step 7: Modify the driver's attach function
Change the driver attach function prototype :
{driver_name}_attach(struct i2c_device *device) --> {driver_name}_attach(struct
i2c_adapter *adap, int addr , unsigned short flags, int kind)
Create a i2c_client client...
Add the following (where "decoder" is a reference to a struct for the driver
info:
struct i2c_client *client;
client = kmalloc(sizeof(*client), GFP_KERNEL);
if(client == NULL)
return -ENOMEM;
client_template.adapter = adap;
client_template.addr = addr;
memcpy(client, &client_template, sizeof(*client));
strcpy(client->name , "{driver_name}");
decoder->client = client;
client->data = decoder;
decoder->addr = addr;
Towards the end of the function, add:
init_MUTEX(&decoder->lock);
i2c_attach_client(client);
Step 8: Modify the driver's detach function
Change the driver detach function prototype :
{driver_name}_detach(struct i2c_device *device) --> {driver_name}_detach(struct
i2c_client *client)
In the beginning of the detach function, add:
i2c_detach_client(client);
Towards the end of the detach function, add:
kfree(client->data);
kfree(client);
Step 9: Modify the driver's command function
Change the driver command function prototype :
Step 10: Add the probe function after the driver's attach function.
Add the following code:
static int {driver_name}_probe(struct i2c_adapter *adap)
{
return i2c_probe(adap, &addr_data, {driver_name}_attach);
}
Step 11: Modify the driver's i2c_driver
Find the i2c_driver , such as
static struct i2c_driver i2c_driver_saa7110
It is usually located towards the end of the driver
Replace the values from I2C_DRIVERID_{something} to {driver_name}_attach, and
add the following
I2C_DRIVERID_{driver_name} , // verify by looking in include/linux/i2c-id.h
I2C_DF_NOTIFY,
{driver_name}_probe,
....
Step 12: Adding the i2c_client
Add the i2c_client to the driver. Add the following code:
static struct i2c_client client_template = {
"{driver_name}_client",
-1,
0,
0,
NULL,
{i2c_driver reference}
};
Step 13: Registering and Unregistering
Replace i2c_register_driver with i2c_add_driver
Replace i2c_unregister_driver with i2c_del_driver
-------------------------------------------------------
Example:
The following patch provides the i2c coversion patch for the saa7110 driver
based on the above guide (for clarity).
--- drivers/media/video/saa7110.c.old Fri Jun 28 10:22:52 2002
+++ drivers/media/video/saa7110.c Thu Jul 4 16:51:08 2002
@@ -26,7 +26,7 @@
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <linux/i2c-old.h>
+#include <linux/i2c.h>
#include <linux/videodev.h>
#include "linux/video_decoder.h"
@@ -37,13 +37,31 @@
#define I2C_SAA7110 0x9C /* or 0x9E */
+#define IF_NAME "saa7110"
#define I2C_DELAY 10 /* 10 us or 100khz */
+static unsigned short normal_i2c[] = {34>>1, I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+ normal_i2c, normal_i2c_range,
+ probe, probe_range,
+ ignore, ignore_range,
+ force
+};
+
+static struct i2c_client client_template;
+
struct saa7110 {
- struct i2c_bus *bus;
+ struct i2c_client *client;
int addr;
unsigned char reg[36];
-
+ struct semaphore lock;
int norm;
int input;
int enable;
@@ -54,67 +72,10 @@
};
/* ----------------------------------------------------------------------- */
-/* I2C support functions */
-/* ----------------------------------------------------------------------- */
-static
-int saa7110_write(struct saa7110 *decoder, unsigned char subaddr, unsigned char data)
-{
- int ack;
-
- LOCK_I2C_BUS(decoder->bus);
- i2c_start(decoder->bus);
- i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
- i2c_sendbyte(decoder->bus, subaddr, I2C_DELAY);
- ack = i2c_sendbyte(decoder->bus, data, I2C_DELAY);
- i2c_stop(decoder->bus);
- decoder->reg[subaddr] = data;
- UNLOCK_I2C_BUS(decoder->bus);
- return ack;
-}
-
-static
-int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len)
-{
- unsigned subaddr = *data;
-
- LOCK_I2C_BUS(decoder->bus);
- i2c_start(decoder->bus);
- i2c_sendbyte(decoder->bus,decoder->addr,I2C_DELAY);
- while (len-- > 0) {
- if (i2c_sendbyte(decoder->bus,*data,0)) {
- i2c_stop(decoder->bus);
- UNLOCK_I2C_BUS(decoder->bus);
- return -EAGAIN;
- }
- decoder->reg[subaddr++] = *data++;
- }
- i2c_stop(decoder->bus);
- UNLOCK_I2C_BUS(decoder->bus);
-
- return 0;
-}
-
-static
-int saa7110_read(struct saa7110* decoder)
-{
- int data;
-
- LOCK_I2C_BUS(decoder->bus);
- i2c_start(decoder->bus);
- i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
- i2c_start(decoder->bus);
- i2c_sendbyte(decoder->bus, decoder->addr | 1, I2C_DELAY);
- data = i2c_readbyte(decoder->bus, 1);
- i2c_stop(decoder->bus);
- UNLOCK_I2C_BUS(decoder->bus);
- return data;
-}
-
-/* ----------------------------------------------------------------------- */
/* SAA7110 functions */
/* ----------------------------------------------------------------------- */
static
-int saa7110_selmux(struct i2c_device *device, int chan)
+int saa7110_selmux(struct i2c_client *client, int chan)
{
static const unsigned char modes[9][8] = {
/* mode 0 */ { 0x00, 0xD9, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 },
@@ -126,61 +87,59 @@
/* mode 6 */ { 0x80, 0x59, 0x17, 0x42, 0xA3, 0x44, 0x75, 0x12 },
/* mode 7 */ { 0x80, 0x9A, 0x17, 0xB1, 0x13, 0x60, 0xB5, 0x14 },
/* mode 8 */ { 0x80, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21 } };
- struct saa7110* decoder = device->data;
const unsigned char* ptr = modes[chan];
- saa7110_write(decoder,0x06,ptr[0]); /* Luminance control */
- saa7110_write(decoder,0x20,ptr[1]); /* Analog Control #1 */
- saa7110_write(decoder,0x21,ptr[2]); /* Analog Control #2 */
- saa7110_write(decoder,0x22,ptr[3]); /* Mixer Control #1 */
- saa7110_write(decoder,0x2C,ptr[4]); /* Mixer Control #2 */
- saa7110_write(decoder,0x30,ptr[5]); /* ADCs gain control */
- saa7110_write(decoder,0x31,ptr[6]); /* Mixer Control #3 */
- saa7110_write(decoder,0x21,ptr[7]); /* Analog Control #2 */
+ i2c_smbus_write_byte_data(client,0x06,ptr[0]); /* Luminance control */
+ i2c_smbus_write_byte_data(client,0x20,ptr[1]); /* Analog Control #1 */
+ i2c_smbus_write_byte_data(client,0x21,ptr[2]); /* Analog Control #2 */
+ i2c_smbus_write_byte_data(client,0x22,ptr[3]); /* Mixer Control #1 */
+ i2c_smbus_write_byte_data(client,0x2C,ptr[4]); /* Mixer Control #2 */
+ i2c_smbus_write_byte_data(client,0x30,ptr[5]); /* ADCs gain control */
+ i2c_smbus_write_byte_data(client,0x31,ptr[6]); /* Mixer Control #3 */
+ i2c_smbus_write_byte_data(client,0x21,ptr[7]); /* Analog Control #2 */
return 0;
}
static
-int determine_norm(struct i2c_device* dev)
+int determine_norm(struct i2c_client* client)
{
- struct saa7110* decoder = dev->data;
int status;
/* mode changed, start automatic detection */
- status = saa7110_read(decoder);
+ status = i2c_smbus_read_byte(client);
if ((status & 3) == 0) {
- saa7110_write(decoder,0x06,0x80);
+ i2c_smbus_write_byte_data(client,0x06,0x80);
if (status & 0x20) {
- DEBUG(printk(KERN_INFO "%s: norm=bw60\n",dev->name));
- saa7110_write(decoder,0x2E,0x81);
+ DEBUG(printk(KERN_INFO "%s: norm=bw60\n",adp->name));
+ i2c_smbus_write_byte_data(client,0x2E,0x81);
return VIDEO_MODE_NTSC;
}
- DEBUG(printk(KERN_INFO "%s: norm=bw50\n",dev->name));
- saa7110_write(decoder,0x2E,0x9A);
+ DEBUG(printk(KERN_INFO "%s: norm=bw50\n",adp->name));
+ i2c_smbus_write_byte_data(client,0x2E,0x9A);
return VIDEO_MODE_PAL;
}
- saa7110_write(decoder,0x06,0x00);
+ i2c_smbus_write_byte_data(client,0x06,0x00);
if (status & 0x20) { /* 60Hz */
- DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",dev->name));
- saa7110_write(decoder,0x0D,0x06);
- saa7110_write(decoder,0x11,0x2C);
- saa7110_write(decoder,0x2E,0x81);
+ DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",adp->name));
+ i2c_smbus_write_byte_data(client,0x0D,0x06);
+ i2c_smbus_write_byte_data(client,0x11,0x2C);
+ i2c_smbus_write_byte_data(client,0x2E,0x81);
return VIDEO_MODE_NTSC;
}
/* 50Hz -> PAL/SECAM */
- saa7110_write(decoder,0x0D,0x06);
- saa7110_write(decoder,0x11,0x59);
- saa7110_write(decoder,0x2E,0x9A);
+ i2c_smbus_write_byte_data(client,0x0D,0x06);
+ i2c_smbus_write_byte_data(client,0x11,0x59);
+ i2c_smbus_write_byte_data(client,0x2E,0x9A);
mdelay(150); /* pause 150 ms */
- status = saa7110_read(decoder);
+ status = i2c_smbus_read_byte(client);
if ((status & 0x03) == 0x01) {
DEBUG(printk(KERN_INFO "%s: norm=secam\n",dev->name));
- saa7110_write(decoder,0x0D,0x07);
+ i2c_smbus_write_byte_data(client,0x0D,0x07);
return VIDEO_MODE_SECAM;
}
DEBUG(printk(KERN_INFO "%s: norm=pal\n",dev->name));
@@ -188,7 +147,7 @@
}
static
-int saa7110_attach(struct i2c_device *device)
+int saa7110_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind)
{
static const unsigned char initseq[] = {
0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF0, 0x00, 0x00,
@@ -198,20 +157,28 @@
0xD9, 0x17, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,
0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x81, 0x03,
0x40, 0x75, 0x01, 0x8C, 0x03};
- struct saa7110* decoder;
+ struct saa7110 *decoder;
+ struct i2c_client *client;
int rv;
-
- device->data = decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
- if (device->data == 0)
+ client=kmalloc(sizeof(*client), GFP_KERNEL);
+ if(client == NULL)
return -ENOMEM;
-
- MOD_INC_USE_COUNT;
+ client_template.adapter = adap;
+ client_template.addr = addr;
+ memcpy(client, &client_template, sizeof(*client));
+
+ decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
+ if (decoder == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
/* clear our private data */
- memset(decoder, 0, sizeof(struct saa7110));
- strcpy(device->name, "saa7110");
- decoder->bus = device->bus;
- decoder->addr = device->addr;
+ memset(decoder, 0, sizeof(*decoder));
+ strcpy(client->name, IF_NAME);
+ decoder->client = client;
+ client->data = decoder;
+ decoder->addr = addr;
decoder->norm = VIDEO_MODE_PAL;
decoder->input = 0;
decoder->enable = 1;
@@ -220,40 +187,52 @@
decoder->hue = 32768;
decoder->sat = 32768;
- rv = saa7110_write_block(decoder, initseq, sizeof(initseq));
+ rv = i2c_master_send(client, initseq, sizeof(initseq));
if (rv < 0)
- printk(KERN_ERR "%s_attach: init status %d\n", device->name, rv);
+ printk(KERN_ERR "%s_attach: init status %d\n", client->name, rv);
else {
- saa7110_write(decoder,0x21,0x16);
- saa7110_write(decoder,0x0D,0x04);
- DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", device->name, saa7110_read(decoder)));
- saa7110_write(decoder,0x0D,0x06);
+ i2c_smbus_write_byte_data(client,0x21,0x16);
+ i2c_smbus_write_byte_data(client,0x0D,0x04);
+ DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", client->name, i2c_smbus_read_byte(client)));
+ i2c_smbus_write_byte_data(client,0x0D,0x06);
}
+ init_MUTEX(&decoder->lock);
+ i2c_attach_client(client);
+ MOD_INC_USE_COUNT;
/* setup and implicit mode 0 select has been performed */
return 0;
}
+static
+int saa7110_probe(struct i2c_adapter *adap)
+{
+ return i2c_probe(adap, &addr_data, saa7110_attach);
+}
+
static
-int saa7110_detach(struct i2c_device *device)
+int saa7110_detach(struct i2c_client *client)
{
- struct saa7110* decoder = device->data;
+ struct saa7110* decoder = client->data;
- DEBUG(printk(KERN_INFO "%s_detach\n",device->name));
+ i2c_detach_client(client);
+
+ DEBUG(printk(KERN_INFO "%s_detach\n",client->name));
/* stop further output */
- saa7110_write(decoder,0x0E,0x00);
+ i2c_smbus_write_byte_data(client,0x0E,0x00);
- kfree(device->data);
+ kfree(decoder);
+ kfree(client);
MOD_DEC_USE_COUNT;
return 0;
}
static
-int saa7110_command(struct i2c_device *device, unsigned int cmd, void *arg)
+int saa7110_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
- struct saa7110* decoder = device->data;
+ struct saa7110* decoder = client->data;
int v;
switch (cmd) {
@@ -272,11 +251,11 @@
case DECODER_GET_STATUS:
{
- struct saa7110* decoder = device->data;
+ struct saa7110* decoder = client->data;
int status;
int res = 0;
- status = i2c_read(device->bus,device->addr|1);
+ status = i2c_smbus_read_byte(client);
if (status & 0x40)
res |= DECODER_STATUS_GOOD;
if (status & 0x03)
@@ -301,26 +280,26 @@
v = *(int*)arg;
if (decoder->norm != v) {
decoder->norm = v;
- saa7110_write(decoder, 0x06, 0x00);
+ i2c_smbus_write_byte_data(client, 0x06, 0x00);
switch (v) {
case VIDEO_MODE_NTSC:
- saa7110_write(decoder, 0x0D, 0x06);
- saa7110_write(decoder, 0x11, 0x2C);
- saa7110_write(decoder, 0x30, 0x81);
- saa7110_write(decoder, 0x2A, 0xDF);
+ i2c_smbus_write_byte_data(client, 0x0D, 0x06);
+ i2c_smbus_write_byte_data(client, 0x11, 0x2C);
+ i2c_smbus_write_byte_data(client, 0x30, 0x81);
+ i2c_smbus_write_byte_data(client, 0x2A, 0xDF);
break;
case VIDEO_MODE_PAL:
- saa7110_write(decoder, 0x0D, 0x06);
- saa7110_write(decoder, 0x11, 0x59);
- saa7110_write(decoder, 0x2E, 0x9A);
+ i2c_smbus_write_byte_data(client, 0x0D, 0x06);
+ i2c_smbus_write_byte_data(client, 0x11, 0x59);
+ i2c_smbus_write_byte_data(client, 0x2E, 0x9A);
break;
case VIDEO_MODE_SECAM:
- saa7110_write(decoder, 0x0D, 0x07);
- saa7110_write(decoder, 0x11, 0x59);
- saa7110_write(decoder, 0x2E, 0x9A);
+ i2c_smbus_write_byte_data(client, 0x0D, 0x07);
+ i2c_smbus_write_byte_data(client, 0x11, 0x59);
+ i2c_smbus_write_byte_data(client, 0x2E, 0x9A);
break;
case VIDEO_MODE_AUTO:
- *(int*)arg = determine_norm(device);
+ *(int*)arg = determine_norm(client);
break;
default:
return -EPERM;
@@ -334,7 +313,7 @@
return -EINVAL;
if (decoder->input != v) {
decoder->input = v;
- saa7110_selmux(device, v);
+ saa7110_selmux(client, v);
}
break;
@@ -349,7 +328,7 @@
v = *(int*)arg;
if (decoder->enable != v) {
decoder->enable = v;
- saa7110_write(decoder,0x0E, v ? 0x18 : 0x00);
+ i2c_smbus_write_byte_data(client,0x0E, v ? 0x18 : 0x00);
}
break;
@@ -360,22 +339,22 @@
if (decoder->bright != pic->brightness) {
/* We want 0 to 255 we get 0-65535 */
decoder->bright = pic->brightness;
- saa7110_write(decoder, 0x19, decoder->bright >> 8);
+ i2c_smbus_write_byte_data(client, 0x19, decoder->bright >> 8);
}
if (decoder->contrast != pic->contrast) {
/* We want 0 to 127 we get 0-65535 */
decoder->contrast = pic->contrast;
- saa7110_write(decoder, 0x13, decoder->contrast >> 9);
+ i2c_smbus_write_byte_data(client, 0x13, decoder->contrast >> 9);
}
if (decoder->sat != pic->colour) {
/* We want 0 to 127 we get 0-65535 */
decoder->sat = pic->colour;
- saa7110_write(decoder, 0x12, decoder->sat >> 9);
+ i2c_smbus_write_byte_data(client, 0x12, decoder->sat >> 9);
}
if (decoder->hue != pic->hue) {
/* We want -128 to 127 we get 0-65535 */
decoder->hue = pic->hue;
- saa7110_write(decoder, 0x07, (decoder->hue>>8)-128);
+ i2c_smbus_write_byte_data(client, 0x07, (decoder->hue>>8)-128);
}
}
break;
@@ -383,7 +362,7 @@
case DECODER_DUMP:
for (v=0; v<34; v+=16) {
int j;
- DEBUG(printk(KERN_INFO "%s: %03x\n",device->name,v));
+ DEBUG(printk(KERN_INFO "%s: %03x\n",client->name,v));
for (j=0; j<16; j++) {
DEBUG(printk(KERN_INFO " %02x",decoder->reg[v+j]));
}
@@ -402,24 +381,30 @@
static struct i2c_driver i2c_driver_saa7110 =
{
- "saa7110", /* name */
-
- I2C_DRIVERID_VIDEODECODER, /* in i2c.h */
- I2C_SAA7110, I2C_SAA7110+1, /* Addr range */
-
- saa7110_attach,
+ IF_NAME, /* name */
+ I2C_DRIVERID_SAA7110, /* in i2c.h */
+ I2C_DF_NOTIFY, /* Addr range */
+ saa7110_probe,
saa7110_detach,
saa7110_command
};
+static struct i2c_client client_template = {
+ "saa7110_client",
+ -1,
+ 0,
+ 0,
+ NULL,
+ &i2c_driver_saa7110
+};
static int saa7110_init(void)
{
- return i2c_register_driver(&i2c_driver_saa7110);
+ return i2c_add_driver(&i2c_driver_saa7110);
}
static void saa7110_exit(void)
{
- i2c_unregister_driver(&i2c_driver_saa7110);
+ i2c_del_driver(&i2c_driver_saa7110);
}
Primitive parallel port is driver for i2c bus, which exploits
features of modern bidirectional parallel ports.
Bidirectional ports have particular bits connected in following way:
|
/-----| R
--o| |-----|
read \-----| /------- Out pin
|/
- -|\
write V
|
---
It means when output is set to 1 we can read the port. Therefore
we can use 2 pins of parallel port as SDA and SCL for i2c bus. It
is not necessary to add any external - additional parts, we can
read and write the same port simultaneously.
I only use register base+2 so it is possible to use all
8 data bits of parallel port for other applications (I have
connected EEPROM and LCD display). I do not use bit Enable Bi-directional
Port. The only disadvantage is we can only support 5V chips.
Layout:
Cannon 25 pin
SDA - connect to pin 14 (Auto Linefeed)
SCL - connect to pin 16 (Initialize Printer)
GND - connect to pin 18-25
+5V - use external supply (I use 5V from 3.5" floppy connector)
no pullups requied
Module parameters:
base = 0xXXX
XXX - 278 or 378
That's all.
Daniel Smolik
marvin@sitour.cz
i2c-velleman driver
-------------------
This is a driver for i2c-hw access for Velleman K9000 and other adapters.
Useful links
------------
Velleman:
http://www.velleman.be/
Velleman K8000 Howto:
http://howto.htlw16.ac.at/k8000-howto.html
K8000 and K8005 libraries
-------------------------
The project has lead to new libs for the Velleman K8000 and K8005..
LIBK8000 v1.99.1 and LIBK8005 v0.21
With these libs you can control the K8000 and K8005 with the original
simple commands which are in the original Velleman software.
Like SetIOchannel, ReadADchannel, SendStepCCWFull and many more.
Via i2c kernel device /dev/velleman
The libs can be found on http://groups.yahoo.com/group/k8000/files/linux/
The Velleman K8000 interface card on http://www.velleman.be/kits/k8000.htm
The Velleman K8005 steppermotorcard on http://www.velleman.be/kits/k8005.htm
SMBus Protocol Summary
======================
The following is a summary of the SMBus protocol. It applies to
all revisions of the protocol (1.0, 1.1, and 2.0).
Certain protocol features which are not supported by
this package are briefly described at the end of this document.
Some adapters understand only the SMBus (System Management Bus) protocol,
which is a subset from the I2C protocol. Fortunately, many devices use
only the same subset, which makes it possible to put them on an SMBus.
......@@ -6,7 +13,7 @@ commands if at all possible (if the device uses only that subset of the
I2C protocol). This makes it possible to use the device driver on both
SMBus adapters and I2C adapters (the SMBus command set is automatically
translated to I2C on I2C adapters, but plain I2C commands can not be
handled at all on a pure SMBus adapter).
handled at all on most pure SMBus adapters).
Below is a list of SMBus commands.
......@@ -109,7 +116,7 @@ S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
SMBus Block Read
================
This command reads a block of upto 32 bytes from a device, from a
This command reads a block of up to 32 bytes from a device, from a
designated register that is specified through the Comm byte. The amount
of data is specified by the device in the Count byte.
......@@ -120,8 +127,90 @@ S Addr Wr [A] Comm [A]
SMBus Block Write
=================
The opposite of the Block Read command, this writes upto 32 bytes to
The opposite of the Block Read command, this writes up to 32 bytes to
a device, to a designated register that is specified through the
Comm byte. The amount of data is specified in the Count byte.
S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
SMBus Block Process Call
========================
SMBus Block Process Call was introduced in Revision 2.0 of the specification.
This command selects a device register (through the Comm byte), sends
1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return.
S Addr Wr [A] Comm [A] Count [A] Data [A] ...
S Addr Rd [A] [Count] A [Data] ... A P
SMBus Host Notify
=================
This command is sent from a SMBus device acting as a master to the
SMBus host acting as a slave.
It is the same form as Write Word, with the command code replaced by the
alerting device's address.
[S] [HostAddr] [Wr] A [DevAddr] A [DataLow] A [DataHigh] A [P]
Packet Error Checking (PEC)
===========================
Packet Error Checking was introduced in Revision 1.1 of the specification.
PEC adds a CRC-8 error-checking byte to all transfers.
Address Resolution Protocol (ARP)
=================================
The Address Resolution Protocol was introduced in Revision 2.0 of
the specification. It is a higher-layer protocol which uses the
messages above.
ARP adds device enumeration and dynamic address assignment to
the protocol. All ARP communications use slave address 0x61 and
require PEC checksums.
I2C Block Transactions
======================
The following I2C block transactions are supported by the
SMBus layer and are described here for completeness.
I2C block transactions do not limit the number of bytes transferred
but the SMBus layer places a limit of 32 bytes.
I2C Block Read
==============
This command reads a block of bytes from a device, from a
designated register that is specified through the Comm byte.
S Addr Wr [A] Comm [A]
S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
I2C Block Read (2 Comm bytes)
=============================
This command reads a block of bytes from a device, from a
designated register that is specified through the two Comm bytes.
S Addr Wr [A] Comm1 [A] Comm2 [A]
S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
I2C Block Write
===============
The opposite of the Block Read command, this writes bytes to
a device, to a designated register that is specified through the
Comm byte. Note that command lengths of 0, 2, or more bytes are
supported as they are indistinguishable from data.
S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
......@@ -59,16 +59,16 @@ Algorithm drivers
i2c-algo-8xx: An algorithm for CPM's I2C device in Motorola 8xx processors (NOT BUILT BY DEFAULT)
i2c-algo-bit: A bit-banging algorithm
i2c-algo-pcf: A PCF 8584 style algorithm
i2c-algo-ppc405: An algorithm for the I2C device in IBM 405xx processors (NOT BUILT BY DEFAULT)
i2c-algo-ibmocp: An algorithm for the I2C device in IBM 4xx processors (NOT BUILT BY DEFAULT)
Adapter drivers
---------------
i2c-elektor: Elektor ISA card (uses i2c-algo-pcf)
i2c-elv: ELV parallel port adapter (uses i2c-algo-bit)
i2c-pcf-epp: PCF8584 on a EPP parallel port (uses i2c-algo-pcf) (BROKEN - missing i2c-pcf-epp.h)
i2c-pcf-epp: PCF8584 on a EPP parallel port (uses i2c-algo-pcf) (NOT mkpatched)
i2c-philips-par: Philips style parallel port adapter (uses i2c-algo-bit)
i2c-ppc405: IBM 405xx processor I2C device (uses i2c-algo-ppc405) (NOT BUILT BY DEFAULT)
i2c-adap_ibmocp: IBM 4xx processor I2C device (uses i2c-algo-ibmocp) (NOT BUILT BY DEFAULT)
i2c-pport: Primitive parallel port adapter (uses i2c-algo-bit)
i2c-rpx: RPX board Motorola 8xx I2C device (uses i2c-algo-8xx) (NOT BUILT BY DEFAULT)
i2c-velleman: Velleman K9000 parallel port adapter (uses i2c-algo-bit)
......
......@@ -365,7 +365,7 @@ The detect client function
The detect client function is called by i2c_probe or i2c_detect.
The `kind' parameter contains 0 if this call is due to a `force'
parameter, and 0 otherwise (for i2c_detect, it contains 0 if
parameter, and -1 otherwise (for i2c_detect, it contains 0 if
this call is due to the generic `force' parameter, and the chip type
number if it is due to a specific `force' parameter).
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment