Showing posts with label i2c. Show all posts
Showing posts with label i2c. Show all posts

Sunday, 4 January 2015

I2c Learning

https://www.kernel.org/doc/htmldocs/device-drivers/i2c.html

http://pete.akeo.ie/2011/08/writing-linux-device-driver-for-kernels.html#uds-search-results



Writing I2C Bus driver
-I2c was developed by Philips
-System management Bus(SMBus) is based on this protocol
-I2c has two line bus.One is Serial Data Line(SDL) and other is Serial Clock Line(SCL).
-Pull up resister are requied in SDL and SCL because pin in the chip can only put the line low or other wise the are floating VDD.
-In I2C mechanism, all the devices are considered as node connected to same medium.
-If a node wants to transmit some data, it can determine whether any other node is transmitting data by letting the pull up resistor to make the logical line to1 and monitor the line state.If any nodes pulls the line to 0, then other nodes can detect that some node is transmitting data.
-I2C protocol supports 10 bit addressing but most of the devices supports only 7 bit addressing (slave addresses). So a maximum of 127 devices can connect on a single bus.
Speed
Standard mode : 100 kbps
Fast mode : 400 kbps
 

More about I2C

  1. Every device connected to I2C lines has a unique address.
  2. Master-slave relationship exist between device and the chip.
  3. Master can be either transmitter or receivers.
  4. I2C is a multi-master bus which has collision detection and mechanisms to prevent data corruption when 2 or more master initiates data transfer at same time. 
  5. It is an 8 bit serial bus which bidirectional data transfer is possible.
Many number of devices can be connected to the same bus.                                        We can just try to see how we can configure I2C adapter, bus driver etc.            

Terminology
===========

When we talk about I2C, we use the following terms:
  Bus    -> Algorithm
            Adapter
  Device -> Driver
            Client


-An Algorithm driver contains general code that can be used for a whole class
of I2C adapters. Each specific adapter driver either depends on one algorithm
driver, or includes its own implementation

-A Driver driver (yes, this sounds ridiculous, sorry) contains the general
code to access some type of device. Each detected device gets its own
data in the Client structure. Usually, Driver and Client are more closely
integrated than Algorithm and Adapter.

-A Driver driver (yes, this sounds ridiculous, sorry) contains the general
code to access some type of device. Each detected device gets its own
data in the Client structure. Usually, Driver and Client are more closely
integrated than Algorithm and Adapter.

-At this time, Linux only operates I2C (or SMBus) in master mode; you can't
use these APIs to make a Linux system behave as a slave/device, either to
speak a custom protocol or to emulate some other device.

                                                                                                                    
Writing an I2C Driver
struct i2c_driver {
  unsigned int class;
  int (* attach_adapter) (struct i2c_adapter *);
  int (* probe) (struct i2c_client *, const struct i2c_device_id *);
  int (* remove) (struct i2c_client *);
  void (* shutdown) (struct i2c_client *);                               /* optional */
  int (* suspend) (struct i2c_client *, pm_message_t mesg);             /* optional */
 int (* resume) (struct i2c_client *);                                   /* optional */
  void (* alert) (struct i2c_client *, unsigned int data);
  int (* command) (struct i2c_client *client, unsigned int cmd, void *arg);/* optional deprecated */
  struct device_driver driver;
  const struct i2c_device_id * id_table;
  int (* detect) (struct i2c_client *, struct i2c_board_info *);
  const unsigned short * address_list;
  struct list_head clients;
};
 
struct i2c_client {
  unsigned short flags;
  unsigned short addr;
  char name[I2C_NAME_SIZE];
  struct i2c_adapter * adapter;
  struct device dev;
  int irq;
  struct list_head detected;
  i2c_slave_cb_t slave_cb;
}; 
 
-you will implement a single driver structure, and instantiate all clients from it.  
-a driver structure contains general access routines, and should be zero-initialized except for fields with data you provide.
-A client structure holds device-specific information like the driver model device node, and its I2C address.
-In driver strucure,Name field should match the module name.  If the driver name doesn't match the module name, the module won't be automatically loaded (hotplug/coldplug).


Accessing the client
====================
-To write/read information to client

-I have found it useful to define foo_read and foo_write functions for this.
For some cases, it will be easier to call the i2c functions directly,
but many chips have some kind of register-value idea that can easily
be encapsulated.
 

The below functions are simple examples, and should not be copied
literally. 

 int foo_read_value(struct i2c_client *client, u8 reg)
{
        if (reg < 0x10) /* byte-sized register */
                return i2c_smbus_read_byte_data(client, reg);
        else            /* word-sized register */
                return i2c_smbus_read_word_data(client, reg);
}

int foo_write_value(struct i2c_client *client, u8 reg, u16 value)
{
        if (reg == 0x10)        /* Impossible to write - driver error! */
                return -EINVAL;
        else if (reg < 0x10)    /* byte-sized register */
                return i2c_smbus_write_byte_data(client, reg, value);
        else                    /* word-sized register */
                return i2c_smbus_write_word_data(client, reg, value);
}
 


Device/Driver Binding
---------------------
-System infrastructure , typically  board-specific initialization code or boot firmware, reports what I2C devices exist.  For example, there may be a table, in the kernel or from the boot loader, identifying I2C devices and linking them to board-specific configuration information about IRQs and other wiring artifacts, chip type, and so on.

 That could be used to create i2c_client objects(device file) for each I2C device.

-I2C device drivers using this binding model work just like any other
kind of driver in Linux:  they provide a probe() method to bind to
those devices, and a remove() method to unbind.

        static int foo_probe(struct i2c_client *client,
                             const struct i2c_device_id *id);//for binding
        static int foo_remove(struct i2c_client *client);//for unbinding



-Remember that the i2c_driver does not create those client handles.  The handle may be used during foo_probe().  If foo_probe() reports success (zero not a negative status code) it may save the handle and use it until foo_remove() returns.
 

-The probe function is called when an entry in the id_table name field
matches the device's name. It is passed the entry that was matched so
the driver knows which one in the table matched.


Device Creation
---------------
-If you know for a fact that an I2C device is connected to a given I2C bus, you can instantiate that device by simply filling an i2c_board_info structure with the device address and driver name, and calling i2c_new_device(). This will create device.

-Then the driver core will take care of finding the right driver and will call its probe() method.
-If a driver supports different device types, you can specify the type you want using the type field.  You can also specify an IRQ and platform data if needed.
-Sometimes you know that a device is connected to a given I2C bus, but you don't know the exact address it uses.
-Sometimes you know that a device is connected to a given I2C bus, but you
don't know the exact address it uses.

- In that case, you can use the i2c_new_probed_device() variant, which is
similar to i2c_new_device(), except that it takes an additional list of
possible I2C addresses to probe.

-The call to i2c_new_device() or i2c_new_probed_device() typically happens
in the I2C bus driver.




Device Detection
----------------





Device Deletion
---------------

-Each I2C device which has been created using i2c_new_device() or i2c_new_probed_device() can be unregistered by calling i2c_unregister_device(). 
- If you don't call it explicitly, it will be called automatically before the underlying I2C bus itself is removed, as a device can't survive its parent in the device driver model.

Initializing the driver
=======================
static int __init foo_init(void)
{
        return i2c_add_driver(&foo_driver);
}

static void __exit foo_cleanup(void)
{
        i2c_del_driver(&foo_driver);
}

/* Substitute your own name and email address */
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");

/* a few non-GPL license types are also allowed */
MODULE_LICENSE("GPL");

module_init(foo_init);
module_exit(foo_cleanup);
-Note that some functions are marked by `__init'.  These functions can be removed after kernel booting (or module loading) is completed. Likewise, functions marked by `__exit' are dropped by the compiler when the code is built into the kernel, as they would never be called.



Power Management
================
-activating a system wakeup mechanism -- do that in the suspend() method.
The resume() method should reverse what the suspend() method does.




System Shutdown
===============

If your I2C device needs special handling when the system shuts down
or reboots (including kexec) -- like turning something off -- use a
shutdown() method.

Again, this is a standard driver model call, working just like it
would for any other driver stack:  the calls can sleep, and can use
I2C messaging.

Command function
================

A generic ioctl-like function call back is supported. You will seldom
need this, and its use is deprecated anyway, so newer design should not
use it.


Sending and receiving
=====================

If you want to communicate with your device, there are several functions
to do this. You can find all of them in <linux/i2c.h>.

If you can choose between plain I2C communication and SMBus level
communication, please use the latter. All adapters understand SMBus level
commands, but only some of them understand plain I2C!



Documentation of I2C (user space):(ref dev-interface)

- i2c devices are controlled by a kernel driver. But it is also possible to access all devices on an adapter from userspace, through the /dev interface.
-Each registered i2c adapter gets a number, counting from 0.
-You can examine /sys/class/i2c-dev/ to see what number corresponds to which adapter.
-Alternatively, you can run "i2cdetect -l" to obtain a formated list of all
i2c adapters present on your system at a given time.

-I2C device files are character device files with major device number 89
and a minor device number corresponding to the number assigned as
explained above.


C example
=========
-So let's say you want to access an i2c adapter from a C program

-The first thing to do is "#include <linux/i2c-dev.h>".

-Please note that there are two files named "i2c-dev.h" out there, one is distributed
with the Linux kernel and is meant to be included from kernel driver code, the other one is distributed with i2c-tools and is meant to be included from user-space programs. You obviously want the second one here 


-Next thing, open the device file, as follows:

  int file;
  int adapter_nr = 2; /* probably dynamically determined */
  char filename[20];

  snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
  file = open(filename, O_RDWR);
  if (file < 0) {
    /* ERROR HANDLING; you can check errno to see what went wrong */
    exit(1);
  }

-When you have opened the device, you must specify with what device
address you want to communicate:

  int addr = 0x40; /* The I2C address */

  if (ioctl(file, I2C_SLAVE, addr) < 0) {
    /* ERROR HANDLING; you can check errno to see what went wrong */
    exit(1);
  }

-Well, you are all set up now. You can now use SMBus commands or plain I2C to communicate with your device. SMBus commands are preferred if the device supports them. Both are illustrated below.


 __u8 register = 0x10; /* Device register to access */
  __s32 res;
  char buf[10];

  /* Using SMBus commands */
  res = i2c_smbus_read_word_data(file, register);
  if (res < 0) {
    /* ERROR HANDLING: i2c transaction failed */
  } else {
    /* res contains the read word */
  }

  /* Using I2C Write, equivalent of
     i2c_smbus_write_word_data(file, register, 0x6543) */
  buf[0] = register;
  buf[1] = 0x43;
  buf[2] = 0x65;
  if (write(file, buf, 3) ! =3) {
    /* ERROR HANDLING: i2c transaction failed */
  }

  /* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */
  if (read(file, buf, 1) != 1) {
    /* ERROR HANDLING: i2c transaction failed */
  } else {
    /* buf[0] contains the read byte */
  }
-Note that only a subset of the I2C and SMBus protocols can be achieved by the means of read() and write() calls. In particular, so-called combined transactions (mixing read and write messages in the same transaction) aren't supported. For this reason, this interface is almost never used by user-space programs.


I2C Core-The I2C core is a code base consisting of routines and data structures available to host adapter drivers and client drivers.

Comment to this blog if any query




Monday, 1 December 2014

I2C devices on BBB

Enable the I2C devices on the BeagleBone Black

On the BeagleBone Black, it's not all of the /dev/i2c-* devices that are enabled by default. The other i2c devices must be enabled before they can be used.

To enable the I2c-1 on the BeagleBone Black Rev A, B and C:
  1. Rev A/B: Open the file /media/BEAGLEBONE/uEnv.txt in an editor (vim/nano)
  2. Rec C: Open the file /boot/uboot/uEnv.txt in an editor (vim/nano)
  3. Add the key "capemgr.enable_partno="
  4. Add the ports you want to enable, comma separated (BB-I2C0, BB-I2C1, etc)
  5. Reboot
An example line looks like this:

root@beaglebone:/dev# cat /media/BEAGLEBONE/uEnv.txt
optargs=quiet drm.debug=7 capemgr.enable_partno=BB-I2C1


After reboot, the device is present in the device list:
root@beaglebone:/dev# ls -l /dev/i2c*
crw-rw---- 1 root tty     249, 0 Jan  1 01:18 /dev/ttyO0
crw-rw---- 1 root dialout 249, 4 Jan  1 01:18 /dev/ttyO4

Note: The I2C devices do not map one-to-one with the devices in /dev/. I.e. I2C-1 does not necessarily map to /dev/i2c-1, it could just as well be one of the other devs, e.g. /dev/i2c-2.

Testing the I2C devices


You can use the standard Linux i2c tools to test your i2c setup:

List all the enabled devices:
root@beaglebone:/dev# i2cdetect -l
i2c-0   i2c             OMAP I2C adapter                        I2C adapter
i2c-1   i2c             OMAP I2C adapter                        I2C adapter
Scan all addresses on one device:
root@beaglebone:/dev# i2cdetect -r 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0 using read byte commands.
I will probe address range 0x03-0x77.
Continue? [Y/n] Y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- UU -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- UU -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: UU -- -- -- -- -- -- --
Write one byte to a device and an address:

i2cset -y 2 0x77 0xf4 0x34

Read one byte from a device and an address:

i2cdump -y 2 0x77


JavaScript / Node.js

In JavaScript / Node.js you can use the package "i2c" or the latest version of "bonescript" that includes the same package.
 - npm install i2c
 - npm install bonescript

I've had some problems with crashes in the i2c module (segmentation faults).

If you just need to read and write single bytes, you can also do this using normal file system (open /dev/i2c-1 for read+write) and set the device address using the "ioctl" module:
 - npm install ioctl

The code sequence:
1. Open /dev/i2c-1 for read+write
2. Use ioctl to set slave address: ioctl(fileHandle, I2C_SLAVE, address)

(I2C_SLAVE = 0x0703 )
Reference: 
http://beaglebone.cameon.net/home/i2c-devices






Documentation of I2c on 

Usually, i2c devices are controlled by a kernel driver. But it is also
possible to access all devices on an adapter from userspace, through
the /dev interface. You need to load module i2c-dev for this.

Each registered i2c adapter gets a number, counting from 0. You can
examine /sys/class/i2c-dev/ to see what number corresponds to which adapter.
Alternatively, you can run "i2cdetect -l" to obtain a formated list of all
i2c adapters present on your system at a given time. i2cdetect is part of
the i2c-tools package.

I2C device files are character device files with major device number 89
and a minor device number corresponding to the number assigned as 
explained above. They should be called "i2c-%d" (i2c-0, i2c-1, ..., 
i2c-10, ...). All 256 minor device numbers are reserved for i2c.


C example
=========

So let's say you want to access an i2c adapter from a C program. The
first thing to do is "#include <linux/i2c-dev.h>". Please note that
there are two files named "i2c-dev.h" out there, one is distributed
with the Linux kernel and is meant to be included from kernel
driver code, the other one is distributed with i2c-tools and is
meant to be included from user-space programs. You obviously want
the second one here.

Now, you have to decide which adapter you want to access. You should
inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to decide this.
Adapter numbers are assigned somewhat dynamically, so you can not
assume much about them. They can even change from one boot to the next.

Next thing, open the device file, as follows:

  int file;
  int adapter_nr = 2; /* probably dynamically determined */
  char filename[20];
  
  snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
  file = open(filename, O_RDWR);
  if (file < 0) {
    /* ERROR HANDLING; you can check errno to see what went wrong */
    exit(1);
  }

When you have opened the device, you must specify with what device
address you want to communicate:

  int addr = 0x40; /* The I2C address */

  if (ioctl(file, I2C_SLAVE, addr) < 0) {
    /* ERROR HANDLING; you can check errno to see what went wrong */
    exit(1);
  }

Well, you are all set up now. You can now use SMBus commands or plain
I2C to communicate with your device. SMBus commands are preferred if
the device supports them. Both are illustrated below.

  __u8 reg = 0x10; /* Device register to access */
  __s32 res;
  char buf[10];

  /* Using SMBus commands */
  res = i2c_smbus_read_word_data(file, reg);
  if (res < 0) {
    /* ERROR HANDLING: i2c transaction failed */
  } else {
    /* res contains the read word */
  }

  /* Using I2C Write, equivalent of 
     i2c_smbus_write_word_data(file, reg, 0x6543) */
  buf[0] = reg;
  buf[1] = 0x43;
  buf[2] = 0x65;
  if (write(file, buf, 3) != 3) {
    /* ERROR HANDLING: i2c transaction failed */
  }

  /* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */
  if (read(file, buf, 1) != 1) {
    /* ERROR HANDLING: i2c transaction failed */
  } else {
    /* buf[0] contains the read byte */
  }

Note that only a subset of the I2C and SMBus protocols can be achieved by
the means of read() and write() calls. In particular, so-called combined
transactions (mixing read and write messages in the same transaction)
aren't supported. For this reason, this interface is almost never used by
user-space programs.

IMPORTANT: because of the use of inline functions, you *have* to use
'-O' or some variation when you compile your program!


Full interface description
==========================

The following IOCTLs are defined:

ioctl(file, I2C_SLAVE, long addr)
  Change slave address. The address is passed in the 7 lower bits of the
  argument (except for 10 bit addresses, passed in the 10 lower bits in this
  case).

ioctl(file, I2C_TENBIT, long select)
  Selects ten bit addresses if select not equals 0, selects normal 7 bit
  addresses if select equals 0. Default 0.  This request is only valid
  if the adapter has I2C_FUNC_10BIT_ADDR.

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.  This request only has an effect if the
  the adapter has I2C_FUNC_SMBUS_PEC; it is still safe if not, it just
  doesn't have any effect.

ioctl(file, I2C_FUNCS, unsigned long *funcs)
  Gets the adapter functionality and puts it in *funcs.

ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)
  Do combined read/write transaction without stop in between.
  Only valid if the adapter has I2C_FUNC_I2C.  The argument is
  a pointer to a

  struct i2c_rdwr_ioctl_data {
      struct i2c_msg *msgs;  /* ptr to array of simple messages */
      int nmsgs;             /* number of messages to exchange */
  }

  The msgs[] themselves contain further pointers into data buffers.
  The function will write or read data to or from that buffers depending
  on whether the I2C_M_RD flag is set in a particular message or not.
  The slave address and whether to use ten bit address mode has to be
  set in each message, overriding the values set with the above ioctl's.

ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)
  Not meant to be called  directly; instead, use the access functions
  below.

You can do plain i2c transactions by using read(2) and write(2) calls.
You do not need to pass the address byte; instead, set it through
ioctl I2C_SLAVE before you try to access the device.

You can do SMBus level transactions (see documentation file smbus-protocol 
for details) through the following functions:
  __s32 i2c_smbus_write_quick(int file, __u8 value);
  __s32 i2c_smbus_read_byte(int file);
  __s32 i2c_smbus_write_byte(int file, __u8 value);
  __s32 i2c_smbus_read_byte_data(int file, __u8 command);
  __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value);
  __s32 i2c_smbus_read_word_data(int file, __u8 command);
  __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value);
  __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value);
  __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values);
  __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, 
                                   __u8 *values);
All these transactions return -1 on failure; you can read errno to see
what happened. The 'write' transactions return 0 on success; the
'read' transactions return the read value, except for read_block, which
returns the number of values read. The block buffers need not be longer
than 32 bytes.

The above functions are all inline functions, that resolve to calls to
the i2c_smbus_access function, that on its turn calls a specific ioctl
with the data in a specific format. Read the source code if you
want to know what happens behind the screens.


Implementation details
======================

For the interested, here's the code flow which happens inside the kernel
when you use the /dev interface to I2C:

1* Your program opens /dev/i2c-N and calls ioctl() on it, as described in
section "C example" above.

2* These open() and ioctl() calls are handled by the i2c-dev kernel
driver: see i2c-dev.c:i2cdev_open() and i2c-dev.c:i2cdev_ioctl(),
respectively. You can think of i2c-dev as a generic I2C chip driver
that can be programmed from user-space.

3* Some ioctl() calls are for administrative tasks and are handled by
i2c-dev directly. Examples include I2C_SLAVE (set the address of the
device you want to access) and I2C_PEC (enable or disable SMBus error
checking on future transactions.)

4* Other ioctl() calls are converted to in-kernel function calls by
i2c-dev. Examples include I2C_FUNCS, which queries the I2C adapter
functionality using i2c.h:i2c_get_functionality(), and I2C_SMBUS, which
performs an SMBus transaction using i2c-core.c:i2c_smbus_xfer().

The i2c-dev driver is responsible for checking all the parameters that
come from user-space for validity. After this point, there is no
difference between these calls that came from user-space through i2c-dev
and calls that would have been performed by kernel I2C chip drivers
directly. This means that I2C bus drivers don't need to implement
anything special to support access from user-space.

5* These i2c-core.c/i2c.h functions are wrappers to the actual
implementation of your I2C bus driver. Each adapter must declare
callback functions implementing these standard calls.
i2c.h:i2c_get_functionality() calls i2c_adapter.algo->functionality(),
while i2c-core.c:i2c_smbus_xfer() calls either
adapter.algo->smbus_xfer() if it is implemented, or if not,
i2c-core.c:i2c_smbus_xfer_emulated() which in turn calls
i2c_adapter.algo->master_xfer().

After your I2C bus driver has processed these requests, execution runs
up the call chain, with almost no processing done, except by i2c-dev to
package the returned data, if any, in suitable format for the ioctl.
 
 
 
EEPROM I2C 
 
/*
  2     Copyright (C) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
  3                                Philip Edelbrock <phil@netroedge.com>
  4     Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
  5     Copyright (C) 2003 IBM Corp.
  6     Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
  7 
  8     This program is free software; you can redistribute it and/or modify
  9     it under the terms of the GNU General Public License as published by
 10     the Free Software Foundation; either version 2 of the License, or
 11     (at your option) any later version.
 12 
 13     This program is distributed in the hope that it will be useful,
 14     but WITHOUT ANY WARRANTY; without even the implied warranty of
 15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16     GNU General Public License for more details.
 17 
 18     You should have received a copy of the GNU General Public License
 19     along with this program; if not, write to the Free Software
 20     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 21 */
 22 
 23 #include <linux/kernel.h>
 24 #include <linux/init.h>
 25 #include <linux/module.h>
 26 #include <linux/slab.h>
 27 #include <linux/jiffies.h>
 28 #include <linux/i2c.h>
 29 #include <linux/mutex.h>
 30 
 31 /* Addresses to scan */
 32 static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
 33                                         0x55, 0x56, 0x57, I2C_CLIENT_END };
 34 
 35 /* Insmod parameters */
 36 I2C_CLIENT_INSMOD_1(eeprom);
 37 
 38 
 39 /* Size of EEPROM in bytes */
 40 #define EEPROM_SIZE             256
 41 
 42 /* possible types of eeprom devices */
 43 enum eeprom_nature {
 44         UNKNOWN,
 45         VAIO,
 46 };
 47 
 48 /* Each client has this additional data */
 49 struct eeprom_data {
 50         struct mutex update_lock;
 51         u8 valid;                       /* bitfield, bit!=0 if slice is valid */
 52         unsigned long last_updated[8];  /* In jiffies, 8 slices */
 53         u8 data[EEPROM_SIZE];           /* Register values */
 54         enum eeprom_nature nature;
 55 };
 56 
 57 
 58 static void eeprom_update_client(struct i2c_client *client, u8 slice)
 59 {
 60         struct eeprom_data *data = i2c_get_clientdata(client);
 61         int i;
 62 
 63         mutex_lock(&data->update_lock);
 64 
 65         if (!(data->valid & (1 << slice)) ||
 66             time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
 67                 dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
 68 
 69                 if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
 70                         for (i = slice << 5; i < (slice + 1) << 5; i += 32)
 71                                 if (i2c_smbus_read_i2c_block_data(client, i,
 72                                                         32, data->data + i)
 73                                                         != 32)
 74                                         goto exit;
 75                 } else {
 76                         for (i = slice << 5; i < (slice + 1) << 5; i += 2) {
 77                                 int word = i2c_smbus_read_word_data(client, i);
 78                                 if (word < 0)
 79                                         goto exit;
 80                                 data->data[i] = word & 0xff;
 81                                 data->data[i + 1] = word >> 8;
 82                         }
 83                 }
 84                 data->last_updated[slice] = jiffies;
 85                 data->valid |= (1 << slice);
 86         }
 87 exit:
 88         mutex_unlock(&data->update_lock);
 89 }
 90 
 91 static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr,
 92                            char *buf, loff_t off, size_t count)
 93 {
 94         struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
 95         struct eeprom_data *data = i2c_get_clientdata(client);
 96         u8 slice;
 97 
 98         if (off > EEPROM_SIZE)
 99                 return 0;
100         if (off + count > EEPROM_SIZE)
101                 count = EEPROM_SIZE - off;
102 
103         /* Only refresh slices which contain requested bytes */
104         for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++)
105                 eeprom_update_client(client, slice);
106 
107         /* Hide Vaio private settings to regular users:
108            - BIOS passwords: bytes 0x00 to 0x0f
109            - UUID: bytes 0x10 to 0x1f
110            - Serial number: 0xc0 to 0xdf */
111         if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) {
112                 int i;
113 
114                 for (i = 0; i < count; i++) {
115                         if ((off + i <= 0x1f) ||
116                             (off + i >= 0xc0 && off + i <= 0xdf))
117                                 buf[i] = 0;
118                         else
119                                 buf[i] = data->data[off + i];
120                 }
121         } else {
122                 memcpy(buf, &data->data[off], count);
123         }
124 
125         return count;
126 }
127 
128 static struct bin_attribute eeprom_attr = {
129         .attr = {
130                 .name = "eeprom",
131                 .mode = S_IRUGO,
132         },
133         .size = EEPROM_SIZE,
134         .read = eeprom_read,
135 };
136 
137 /* Return 0 if detection is successful, -ENODEV otherwise */
138 static int eeprom_detect(struct i2c_client *client, int kind,
139                          struct i2c_board_info *info)
140 {
141         struct i2c_adapter *adapter = client->adapter;
142 
143         /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all
144            addresses 0x50-0x57, but we only care about 0x50. So decline
145            attaching to addresses >= 0x51 on DDC buses */
146         if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51)
147                 return -ENODEV;
148 
149         /* There are four ways we can read the EEPROM data:
150            (1) I2C block reads (faster, but unsupported by most adapters)
151            (2) Word reads (128% overhead)
152            (3) Consecutive byte reads (88% overhead, unsafe)
153            (4) Regular byte data reads (265% overhead)
154            The third and fourth methods are not implemented by this driver
155            because all known adapters support one of the first two. */
156         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)
157          && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
158                 return -ENODEV;
159 
160         strlcpy(info->type, "eeprom", I2C_NAME_SIZE);
161 
162         return 0;
163 }
164 
165 static int eeprom_probe(struct i2c_client *client,
166                         const struct i2c_device_id *id)
167 {
168         struct i2c_adapter *adapter = client->adapter;
169         struct eeprom_data *data;
170         int err;
171 
172         if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
173                 err = -ENOMEM;
174                 goto exit;
175         }
176 
177         memset(data->data, 0xff, EEPROM_SIZE);
178         i2c_set_clientdata(client, data);
179         mutex_init(&data->update_lock);
180         data->nature = UNKNOWN;
181 
182         /* Detect the Vaio nature of EEPROMs.
183            We use the "PCG-" or "VGN-" prefix as the signature. */
184         if (client->addr == 0x57
185          && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
186                 char name[4];
187 
188                 name[0] = i2c_smbus_read_byte_data(client, 0x80);
189                 name[1] = i2c_smbus_read_byte_data(client, 0x81);
190                 name[2] = i2c_smbus_read_byte_data(client, 0x82);
191                 name[3] = i2c_smbus_read_byte_data(client, 0x83);
192 
193                 if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) {
194                         dev_info(&client->dev, "Vaio EEPROM detected, "
195                                  "enabling privacy protection\n");
196                         data->nature = VAIO;
197                 }
198         }
199 
200         /* create the sysfs eeprom file */
201         err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr);
202         if (err)
203                 goto exit_kfree;
204 
205         return 0;
206 
207 exit_kfree:
208         kfree(data);
209 exit:
210         return err;
211 }
212 
213 static int eeprom_remove(struct i2c_client *client)
214 {
215         sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
216         kfree(i2c_get_clientdata(client));
217 
218         return 0;
219 }
220 
221 static const struct i2c_device_id eeprom_id[] = {
222         { "eeprom", 0 },
223         { }
224 };
225 
226 static struct i2c_driver eeprom_driver = {
227         .driver = {
228                 .name   = "eeprom",
229         },
230         .probe          = eeprom_probe,
231         .remove         = eeprom_remove,
232         .id_table       = eeprom_id,
233 
234         .class          = I2C_CLASS_DDC | I2C_CLASS_SPD,
235         .detect         = eeprom_detect,
236         .address_data   = &addr_data,
237 };
238 
239 static int __init eeprom_init(void)
240 {
241         return i2c_add_driver(&eeprom_driver);
242 }
243 
244 static void __exit eeprom_exit(void)
245 {
246         i2c_del_driver(&eeprom_driver);
247 }
248 
249 
250 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
251                 "Philip Edelbrock <phil@netroedge.com> and "
252                 "Greg Kroah-Hartman <greg@kroah.com>");
253 MODULE_DESCRIPTION("I2C EEPROM driver");
254 MODULE_LICENSE("GPL");
255 
256 module_init(eeprom_init);
257 module_exit(eeprom_exit);
258