11cf4323eSThomas Huth /* 21cf4323eSThomas Huth * QTest I2C driver 31cf4323eSThomas Huth * 41cf4323eSThomas Huth * Copyright (c) 2012 Andreas Färber 51cf4323eSThomas Huth * 61cf4323eSThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 or later. 71cf4323eSThomas Huth * See the COPYING file in the top-level directory. 81cf4323eSThomas Huth */ 91cf4323eSThomas Huth #include "qemu/osdep.h" 10*a2ce7dbdSPaolo Bonzini #include "i2c.h" 111cf4323eSThomas Huth #include "libqtest.h" 121cf4323eSThomas Huth 1339397a9aSAlexander Bulekov void qi2c_send(QI2CDevice *i2cdev, const uint8_t *buf, uint16_t len) 141cf4323eSThomas Huth { 151cf4323eSThomas Huth i2cdev->bus->send(i2cdev->bus, i2cdev->addr, buf, len); 161cf4323eSThomas Huth } 171cf4323eSThomas Huth 1839397a9aSAlexander Bulekov void qi2c_recv(QI2CDevice *i2cdev, uint8_t *buf, uint16_t len) 191cf4323eSThomas Huth { 201cf4323eSThomas Huth i2cdev->bus->recv(i2cdev->bus, i2cdev->addr, buf, len); 211cf4323eSThomas Huth } 221cf4323eSThomas Huth 231cf4323eSThomas Huth void i2c_read_block(QI2CDevice *i2cdev, uint8_t reg, 241cf4323eSThomas Huth uint8_t *buf, uint16_t len) 251cf4323eSThomas Huth { 2639397a9aSAlexander Bulekov qi2c_send(i2cdev, ®, 1); 2739397a9aSAlexander Bulekov qi2c_recv(i2cdev, buf, len); 281cf4323eSThomas Huth } 291cf4323eSThomas Huth 301cf4323eSThomas Huth void i2c_write_block(QI2CDevice *i2cdev, uint8_t reg, 311cf4323eSThomas Huth const uint8_t *buf, uint16_t len) 321cf4323eSThomas Huth { 331cf4323eSThomas Huth uint8_t *cmd = g_malloc(len + 1); 341cf4323eSThomas Huth cmd[0] = reg; 351cf4323eSThomas Huth memcpy(&cmd[1], buf, len); 3639397a9aSAlexander Bulekov qi2c_send(i2cdev, cmd, len + 1); 371cf4323eSThomas Huth g_free(cmd); 381cf4323eSThomas Huth } 391cf4323eSThomas Huth 401cf4323eSThomas Huth uint8_t i2c_get8(QI2CDevice *i2cdev, uint8_t reg) 411cf4323eSThomas Huth { 421cf4323eSThomas Huth uint8_t resp[1]; 431cf4323eSThomas Huth i2c_read_block(i2cdev, reg, resp, sizeof(resp)); 441cf4323eSThomas Huth return resp[0]; 451cf4323eSThomas Huth } 461cf4323eSThomas Huth 471cf4323eSThomas Huth uint16_t i2c_get16(QI2CDevice *i2cdev, uint8_t reg) 481cf4323eSThomas Huth { 491cf4323eSThomas Huth uint8_t resp[2]; 501cf4323eSThomas Huth i2c_read_block(i2cdev, reg, resp, sizeof(resp)); 511cf4323eSThomas Huth return (resp[0] << 8) | resp[1]; 521cf4323eSThomas Huth } 531cf4323eSThomas Huth 541cf4323eSThomas Huth void i2c_set8(QI2CDevice *i2cdev, uint8_t reg, uint8_t value) 551cf4323eSThomas Huth { 561cf4323eSThomas Huth i2c_write_block(i2cdev, reg, &value, 1); 571cf4323eSThomas Huth } 581cf4323eSThomas Huth 591cf4323eSThomas Huth void i2c_set16(QI2CDevice *i2cdev, uint8_t reg, uint16_t value) 601cf4323eSThomas Huth { 611cf4323eSThomas Huth uint8_t data[2]; 621cf4323eSThomas Huth 631cf4323eSThomas Huth data[0] = value >> 8; 641cf4323eSThomas Huth data[1] = value & 255; 651cf4323eSThomas Huth i2c_write_block(i2cdev, reg, data, sizeof(data)); 661cf4323eSThomas Huth } 671cf4323eSThomas Huth 681cf4323eSThomas Huth void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr) 691cf4323eSThomas Huth { 701cf4323eSThomas Huth QI2CDevice *i2cdev = g_new0(QI2CDevice, 1); 711cf4323eSThomas Huth 721cf4323eSThomas Huth i2cdev->bus = i2c_bus; 731cf4323eSThomas Huth if (addr) { 741cf4323eSThomas Huth i2cdev->addr = ((QI2CAddress *)addr)->addr; 751cf4323eSThomas Huth } 761cf4323eSThomas Huth return &i2cdev->obj; 771cf4323eSThomas Huth } 781cf4323eSThomas Huth 791cf4323eSThomas Huth void add_qi2c_address(QOSGraphEdgeOptions *opts, QI2CAddress *addr) 801cf4323eSThomas Huth { 811cf4323eSThomas Huth g_assert(addr); 821cf4323eSThomas Huth 831cf4323eSThomas Huth opts->arg = addr; 841cf4323eSThomas Huth opts->size_arg = sizeof(QI2CAddress); 851cf4323eSThomas Huth } 86