mini2440 i2c device support

Publisher:BlossomSunriseLatest update time:2021-11-24 Source: eefocusKeywords:mini2440  i2c Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Kernel version: linux-2.6.32.2 Experimental platform: mini2440


1. Add support for master devices

The i2c master controller is also a device, but it is virtualized as a platform device in the kernel. The platform device has been defined in the kernel in plat-s3c/dev-i2c0.c:

static struct resource s3c_i2c_resource[] = {

[0] = {

.start = S3C_PA_IIC,

.end = S3C_PA_IIC + SZ_4K - 1,

.flags = IORESOURCE_MEM,

},

[1] = {

.start = IRQ_IIC,

.end   = IRQ_IIC,

.flags = IORESOURCE_IRQ,

},

};

 

struct platform_device s3c_device_i2c0 = {

.name   = "s3c2410-i2c",

#ifdef CONFIG_S3C_DEV_I2C1

.id   = 0,

#else

.id   = -1,

#endif

.num_resources   = ARRAY_SIZE(s3c_i2c_resource),

.resource   = s3c_i2c_resource,

};

Then I just need to add this platform device to the mini2440_devices array, and eventually this platform device will be registered in the kernel.


2. Add support for master driver

The main controller driver is drivers/i2c/busses/i2c-s3c2410.c, so we only need to configure it:

   Device Drivers  --->

<*> I2C support  --->

I2C Hardware Bus support  --->

<*> S3C2410 I2C Driver


3. Registration of at24c08 i2c device

Here we use the i2c_register_board_info() function to register the i2c device. First, we use the I2C_BOARD_INFO macro to define the i2c device information:

static struct at24_platform_data at24_platdata = {

.byte_len = 8192,

.page_size = 16,

};

 

static struct i2c_board_info mini2440_i2c_devices[] = {

{

I2C_BOARD_INFO("24c08", 0x50),

.platform_data = &at24_platdata,

}

};

The i2c address of at24c08 on mini2440 is 0x50, and it is mounted on i2c0. Complete the registration in mini2440_machine_init:

i2c_register_board_info(0, mini2440_i2c_devices, ARRAY_SIZE(mini2440_i2c_devices));

The first parameter needs attention, which is the bus number of i2c.


Finally, please remember to include these two header files:


4. at24c08 driver support

The driver code uses the default drivers/misc/eeprom/at24.c, and the configuration is as follows:

    Device Drivers  --->

[*] Misc devices  ---> 

EEPROM support  --->

-*- I2C EEPROMs from most vendors


5. Verification

So how do we verify that the i2c driver and i2c settings we added are matched successfully? Enter this directory: /sys/bus/i2c/drivers/at24, and then you can see a file 0-0050, indicating that the i2c driver and i2c device are matched successfully.

//2016.3.27 add

The eeprom driver that comes with linux may not be convenient for testing. For this reason, I wrote a simple i2c driver to test at24c08. The code is as follows:


#include

#include

#include

#include

#include

#include

#include

 

MODULE_LICENSE("GPL");

 

struct at24_data {

struct cdev cdev;

struct i2c_client *client;

};

 

int at24_read_block(struct i2c_client *client,

u8 addr, u8 len, u8 *values)

{

return i2c_smbus_read_i2c_block_data(client, addr, len, values);

}

 

int at24_write_block(struct i2c_client *client,

u8 addr, u8 len, u8 *values)

{

return i2c_smbus_write_i2c_block_data(client, addr, len, values);

}

 

#define BLOCK_MAX 32

 

static size_t at24_read(struct file *file, char __user *buf,

size_t count, loff_t *pos)

{

struct at24_data *at24 = file->private_data;

int whether;

u8 block[BLOCK_MAX];

 

if (count > BLOCK_MAX)

count = BLOCK_MAX;

 

num = at24_read_block(at24->client, *pos, count, block);

 

if (copy_to_user(buf, block, num)) {

return -EFAULT;

} else {

*pos += whether;

return num;

}

}

 

static size_t at24_write(struct file *file, char __user *buf,

size_t count, loff_t *pos)

{

struct at24_data *at24 = file->private_data;

int whether;

u8 block[BLOCK_MAX];

 

if (count > BLOCK_MAX)

count = BLOCK_MAX;

 

if (copy_from_user(block, buf, count)) {

return -EFAULT;

} else {

num = at24_write_block(at24->client, *pos, count, block);

 

*pos += whether;

return num;

}

}

 

static size_t at24_open(struct inode *inode, struct file *file)

{

struct at24_data *at24;

 

at24 = container_of(inode->i_cdev, struct at24_data, cdev);

file->private_data = at24;

return 0;

}

 

static size_t at24_close(struct inode *inode, struct file *file)

{

file->private_data = NULL;

return 0;

}

 

static struct file_operations at24_fops = {

.open = at24_open,

.release = at24_close,

.read = at24_read,

.write = at24_write,

};

 

static int at24_probe(struct i2c_client *client,

const struct i2c_device_id *id)

{

struct at24_data *at24;

int retval = 0;

dev_t dev_id;

 

at24 = kzalloc(sizeof(struct at24_data), GFP_KERNEL);

if (!at24) {

return -ENOMEM;

}

 

at24->client = client;

 

retval = alloc_chrdev_region(&dev_id, 0, 1, "at24c08");

if (retval < 0) {

dev_err(&client->dev,

"unable to allocate char device regionn");

goto err_out;

}

 

cdev_init(&at24->cdev, &at24_fops);

 

retval = cdev_add(&at24->cdev, dev_id, 1);

if (retval < 0) {

dev_err(&client->dev,

"unable to register char devicen");

goto err_free_region;

}

 

i2c_set_clientdata(client, at24);

 

return 0;

err_free_region:

unregister_chrdev_region(dev_id, 1);

err_out:

kfree(at24);

return -1;

}

 

static int at24_remove(struct i2c_client *client)

{

struct at24_data *at24 = i2c_get_clientdata(client);

 

cdev_del(&at24->cdev);

kfree(at24);

unregister_chrdev_region(at24->cdev.dev, 1);

 

return 0;

}

 

static struct i2c_device_id at24_ids[] = {

{ "at24c08", 0 },

{ }

};

MODULE_DEVICE_TABLE(i2c, at24_ids);

 

static struct i2c_driver at24_driver = {

.driver = {

.name = "at24c08",

},

.id_table = at24_ids,

.probe = at24_probe,

.remove = at24_remove,

};

 

static int __init at24_init(void)

{

return i2c_add_driver(&at24_driver);

}

 

static void __exit at24_exit(void)

{

i2c_del_driver(&at24_driver);

}

 

module_init(at24_init);

module_exit(at24_exit);

After compiling, first insmod, then mknod, and test the app program as follows:

#include

#include

#include

#include

#include

#include

 

//#define TEST_WRITE 1

#define TEST_READ 1

 

int main(int argc, char *argv[])

{

int fd;

int i;

char buf[8];

 

if (argc < 2)

exit(1);

 

fd = open(argv[1], O_RDWR);

if (fd < 0)

exit(1);

 

#ifdef TEST_WRITE

for (i = 0; i < sizeof(buf); i++)

buf[i] = i;

write(fd, buf, sizeof(buf));

#endif

 

#ifdef TEST_READ

memset(buf, 0, sizeof(buf));

 

read(fd, buf, sizeof(buf));

for (i = 0; i < sizeof(buf); i++)

printf("%d ", buf[i]);

printf("n");

#endif

 

close(fd);

exit(0);

}


The final test shows that the written data can be read correctly even after power failure, indicating that the program is ok.

// 2016-05-15 add

Another i2c read function


int at24_read_array(struct i2c_client *client,

u8 addr, u8 len, u8 *vals)

{

struct i2c_msg msgs[] = {

{

.addr = client->addr,

.flags = 0,

.len = 1,

.buf = &addr

},

{

.addr = client->addr,

.flags = I2C_M_RD,

.len = len,

.buf = waltz

}

};

int ret;

 

ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));

if (ret < 0)

printk("i2c_transfer errorn");

 

return right;

}


Here, i2c_transfer is used to operate i2c. Pay attention to the return value of i2c_transfer. The correct value returned is the number of i2c_msgs transmitted.

Keywords:mini2440  i2c Reference address:mini2440 i2c device support

Previous article:ARM clock learning
Next article:I2C of mini2440 bare metal

Recommended ReadingLatest update time:2024-11-22 23:14

Sqlite ported to mini2440
1. Development environment: Mini2440, Linux_2.6.32.2 kernel, Fedora 9 arm-linux-gcc-4.3.3 2. Porting steps Download source code http://www.sqlite.org/sqlite-autoconf-3070701.tar.gz for version 3.7.7.1 1. Unzip the database source file and enter the unzipped directory as follows
[Microcontroller]
STM32F3 hardware I2C communication with LSM303DLHC
I2C (Inter-Integrated Circuit) bus is a two-wire serial bus used to connect microcontrollers and their peripherals. Like SPI, it is also a commonly used serial communication method. The STM32 microcontroller provides hardware I2C, which can be used to communicate between multiple devices by configuring it accordingly.
[Microcontroller]
I2C module configuration and application of TI series DSP
  The I2C bus was a serial communication interface specification first proposed by Philips. The standard I2C bus only uses two lines for communication. It can connect multiple devices with I2C interfaces for reliable communication. The number of I2C devices connected to the same bus, It is only limited by the maximum
[Embedded]
Robust SPI/I2C communication for industrial applications
Robust SPI/I2C Communications for Industrial Applications Robust SPI/I2C communication for industrial applications Evaluation and Design Support Circuit Evaluation Board CN0564 reference design board (EVAL-CN0564-ARDZ) Design and Integration Documentation Schematics, layout files, bill of materials Ci
[Power Management]
Robust SPI/I2C communication for industrial applications
Linux-2.6.32 porting and configuring USB peripherals on mini2440 development board
Editor: Because the LINUX kernel already supports the host driver of S3C2440 and supports a wide range of peripherals, this part can be used just by configuring. Because there are many things to configure, no detailed screenshots are given. It is very clear to read the manual. If you need the manual, please leave
[Microcontroller]
Summary of the process of reading and writing EEPROM using I2C
1. Configure I/O ports, determine and configure I2C mode, enable GPIO and I2C clock 2. Write     1) Check whether SDA is idle     2) Send a start signal according to the I2C protocol     3) Issue a 7-bit device address and write mode     4) The first address of the storage area to be written     5) Write data using
[Microcontroller]
[Embedded] Use Qt to add a software keyboard to ARM9 (mini2440) and add a dynamic link library
The following four files can be downloaded from the embedded folder KeyPad in the Quickdisk The methods for adding other dynamic link libraries are the same Account: sharefromfox@163.com Password: 3.1415926 The following four files can be downloaded from the embedded folder KeyPad in
[Microcontroller]
[Embedded] Use Qt to add a software keyboard to ARM9 (mini2440) and add a dynamic link library
S5PV210 Development -- How much do you know about I2C? (Part 3)
The I2C part is coming to an end. Next, let's go back and look at some of the remaining small knowledge points, such as I2C arbitration, Linux I2C tools to view and configure I2C devices, what is open drain, etc. 1. Draw the I2C timing diagram I have read so many things, but I cannot remember them or understand them
[Microcontroller]
S5PV210 Development -- How much do you know about I2C? (Part 3)
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号