193198b6cSCorey Minyard /* 293198b6cSCorey Minyard * QEMU SMBus host (master) emulation. 393198b6cSCorey Minyard * 493198b6cSCorey Minyard * This code emulates SMBus transactions from the master point of view, 593198b6cSCorey Minyard * it runs the individual I2C transaction to do the SMBus protocol 693198b6cSCorey Minyard * over I2C. 793198b6cSCorey Minyard * 893198b6cSCorey Minyard * Copyright (c) 2007 CodeSourcery. 993198b6cSCorey Minyard * Written by Paul Brook 1093198b6cSCorey Minyard * 1193198b6cSCorey Minyard * This code is licensed under the LGPL. 1293198b6cSCorey Minyard */ 1393198b6cSCorey Minyard 1493198b6cSCorey Minyard #include "qemu/osdep.h" 1593198b6cSCorey Minyard #include "hw/i2c/i2c.h" 1693198b6cSCorey Minyard #include "hw/i2c/smbus_master.h" 1793198b6cSCorey Minyard 1893198b6cSCorey Minyard /* Master device commands. */ 1993198b6cSCorey Minyard int smbus_quick_command(I2CBus *bus, uint8_t addr, int read) 2093198b6cSCorey Minyard { 2193198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, read)) { 2293198b6cSCorey Minyard return -1; 2393198b6cSCorey Minyard } 2493198b6cSCorey Minyard i2c_end_transfer(bus); 2593198b6cSCorey Minyard return 0; 2693198b6cSCorey Minyard } 2793198b6cSCorey Minyard 2893198b6cSCorey Minyard int smbus_receive_byte(I2CBus *bus, uint8_t addr) 2993198b6cSCorey Minyard { 3093198b6cSCorey Minyard uint8_t data; 3193198b6cSCorey Minyard 32*90603c5bSPhilippe Mathieu-Daudé if (i2c_start_recv(bus, addr)) { 3393198b6cSCorey Minyard return -1; 3493198b6cSCorey Minyard } 3593198b6cSCorey Minyard data = i2c_recv(bus); 3693198b6cSCorey Minyard i2c_nack(bus); 3793198b6cSCorey Minyard i2c_end_transfer(bus); 3893198b6cSCorey Minyard return data; 3993198b6cSCorey Minyard } 4093198b6cSCorey Minyard 4193198b6cSCorey Minyard int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data) 4293198b6cSCorey Minyard { 43*90603c5bSPhilippe Mathieu-Daudé if (i2c_start_send(bus, addr)) { 4493198b6cSCorey Minyard return -1; 4593198b6cSCorey Minyard } 4693198b6cSCorey Minyard i2c_send(bus, data); 4793198b6cSCorey Minyard i2c_end_transfer(bus); 4893198b6cSCorey Minyard return 0; 4993198b6cSCorey Minyard } 5093198b6cSCorey Minyard 5193198b6cSCorey Minyard int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command) 5293198b6cSCorey Minyard { 5393198b6cSCorey Minyard uint8_t data; 54*90603c5bSPhilippe Mathieu-Daudé if (i2c_start_send(bus, addr)) { 5593198b6cSCorey Minyard return -1; 5693198b6cSCorey Minyard } 5793198b6cSCorey Minyard i2c_send(bus, command); 58*90603c5bSPhilippe Mathieu-Daudé if (i2c_start_recv(bus, addr)) { 5993198b6cSCorey Minyard i2c_end_transfer(bus); 6093198b6cSCorey Minyard return -1; 6193198b6cSCorey Minyard } 6293198b6cSCorey Minyard data = i2c_recv(bus); 6393198b6cSCorey Minyard i2c_nack(bus); 6493198b6cSCorey Minyard i2c_end_transfer(bus); 6593198b6cSCorey Minyard return data; 6693198b6cSCorey Minyard } 6793198b6cSCorey Minyard 6893198b6cSCorey Minyard int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data) 6993198b6cSCorey Minyard { 70*90603c5bSPhilippe Mathieu-Daudé if (i2c_start_send(bus, addr)) { 7193198b6cSCorey Minyard return -1; 7293198b6cSCorey Minyard } 7393198b6cSCorey Minyard i2c_send(bus, command); 7493198b6cSCorey Minyard i2c_send(bus, data); 7593198b6cSCorey Minyard i2c_end_transfer(bus); 7693198b6cSCorey Minyard return 0; 7793198b6cSCorey Minyard } 7893198b6cSCorey Minyard 7993198b6cSCorey Minyard int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command) 8093198b6cSCorey Minyard { 8193198b6cSCorey Minyard uint16_t data; 82*90603c5bSPhilippe Mathieu-Daudé if (i2c_start_send(bus, addr)) { 8393198b6cSCorey Minyard return -1; 8493198b6cSCorey Minyard } 8593198b6cSCorey Minyard i2c_send(bus, command); 86*90603c5bSPhilippe Mathieu-Daudé if (i2c_start_recv(bus, addr)) { 8793198b6cSCorey Minyard i2c_end_transfer(bus); 8893198b6cSCorey Minyard return -1; 8993198b6cSCorey Minyard } 9093198b6cSCorey Minyard data = i2c_recv(bus); 9193198b6cSCorey Minyard data |= i2c_recv(bus) << 8; 9293198b6cSCorey Minyard i2c_nack(bus); 9393198b6cSCorey Minyard i2c_end_transfer(bus); 9493198b6cSCorey Minyard return data; 9593198b6cSCorey Minyard } 9693198b6cSCorey Minyard 9793198b6cSCorey Minyard int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data) 9893198b6cSCorey Minyard { 99*90603c5bSPhilippe Mathieu-Daudé if (i2c_start_send(bus, addr)) { 10093198b6cSCorey Minyard return -1; 10193198b6cSCorey Minyard } 10293198b6cSCorey Minyard i2c_send(bus, command); 10393198b6cSCorey Minyard i2c_send(bus, data & 0xff); 10493198b6cSCorey Minyard i2c_send(bus, data >> 8); 10593198b6cSCorey Minyard i2c_end_transfer(bus); 10693198b6cSCorey Minyard return 0; 10793198b6cSCorey Minyard } 10893198b6cSCorey Minyard 10993198b6cSCorey Minyard int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, 11093198b6cSCorey Minyard int len, bool recv_len, bool send_cmd) 11193198b6cSCorey Minyard { 11293198b6cSCorey Minyard int rlen; 11393198b6cSCorey Minyard int i; 11493198b6cSCorey Minyard 11593198b6cSCorey Minyard if (send_cmd) { 116*90603c5bSPhilippe Mathieu-Daudé if (i2c_start_send(bus, addr)) { 11793198b6cSCorey Minyard return -1; 11893198b6cSCorey Minyard } 11993198b6cSCorey Minyard i2c_send(bus, command); 12093198b6cSCorey Minyard } 121*90603c5bSPhilippe Mathieu-Daudé if (i2c_start_recv(bus, addr)) { 12293198b6cSCorey Minyard if (send_cmd) { 12393198b6cSCorey Minyard i2c_end_transfer(bus); 12493198b6cSCorey Minyard } 12593198b6cSCorey Minyard return -1; 12693198b6cSCorey Minyard } 12793198b6cSCorey Minyard if (recv_len) { 12893198b6cSCorey Minyard rlen = i2c_recv(bus); 12993198b6cSCorey Minyard } else { 13093198b6cSCorey Minyard rlen = len; 13193198b6cSCorey Minyard } 13293198b6cSCorey Minyard if (rlen > len) { 13393198b6cSCorey Minyard rlen = 0; 13493198b6cSCorey Minyard } 13593198b6cSCorey Minyard for (i = 0; i < rlen; i++) { 13693198b6cSCorey Minyard data[i] = i2c_recv(bus); 13793198b6cSCorey Minyard } 13893198b6cSCorey Minyard i2c_nack(bus); 13993198b6cSCorey Minyard i2c_end_transfer(bus); 14093198b6cSCorey Minyard return rlen; 14193198b6cSCorey Minyard } 14293198b6cSCorey Minyard 14393198b6cSCorey Minyard int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, 14493198b6cSCorey Minyard int len, bool send_len) 14593198b6cSCorey Minyard { 14693198b6cSCorey Minyard int i; 14793198b6cSCorey Minyard 14893198b6cSCorey Minyard if (len > 32) { 14993198b6cSCorey Minyard len = 32; 15093198b6cSCorey Minyard } 15193198b6cSCorey Minyard 152*90603c5bSPhilippe Mathieu-Daudé if (i2c_start_send(bus, addr)) { 15393198b6cSCorey Minyard return -1; 15493198b6cSCorey Minyard } 15593198b6cSCorey Minyard i2c_send(bus, command); 15693198b6cSCorey Minyard if (send_len) { 15793198b6cSCorey Minyard i2c_send(bus, len); 15893198b6cSCorey Minyard } 15993198b6cSCorey Minyard for (i = 0; i < len; i++) { 16093198b6cSCorey Minyard i2c_send(bus, data[i]); 16193198b6cSCorey Minyard } 16293198b6cSCorey Minyard i2c_end_transfer(bus); 16393198b6cSCorey Minyard return 0; 16493198b6cSCorey Minyard } 165