1*93198b6cSCorey Minyard /* 2*93198b6cSCorey Minyard * QEMU SMBus host (master) emulation. 3*93198b6cSCorey Minyard * 4*93198b6cSCorey Minyard * This code emulates SMBus transactions from the master point of view, 5*93198b6cSCorey Minyard * it runs the individual I2C transaction to do the SMBus protocol 6*93198b6cSCorey Minyard * over I2C. 7*93198b6cSCorey Minyard * 8*93198b6cSCorey Minyard * Copyright (c) 2007 CodeSourcery. 9*93198b6cSCorey Minyard * Written by Paul Brook 10*93198b6cSCorey Minyard * 11*93198b6cSCorey Minyard * This code is licensed under the LGPL. 12*93198b6cSCorey Minyard */ 13*93198b6cSCorey Minyard 14*93198b6cSCorey Minyard #include "qemu/osdep.h" 15*93198b6cSCorey Minyard #include "hw/hw.h" 16*93198b6cSCorey Minyard #include "hw/i2c/i2c.h" 17*93198b6cSCorey Minyard #include "hw/i2c/smbus_master.h" 18*93198b6cSCorey Minyard 19*93198b6cSCorey Minyard /* Master device commands. */ 20*93198b6cSCorey Minyard int smbus_quick_command(I2CBus *bus, uint8_t addr, int read) 21*93198b6cSCorey Minyard { 22*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, read)) { 23*93198b6cSCorey Minyard return -1; 24*93198b6cSCorey Minyard } 25*93198b6cSCorey Minyard i2c_end_transfer(bus); 26*93198b6cSCorey Minyard return 0; 27*93198b6cSCorey Minyard } 28*93198b6cSCorey Minyard 29*93198b6cSCorey Minyard int smbus_receive_byte(I2CBus *bus, uint8_t addr) 30*93198b6cSCorey Minyard { 31*93198b6cSCorey Minyard uint8_t data; 32*93198b6cSCorey Minyard 33*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, 1)) { 34*93198b6cSCorey Minyard return -1; 35*93198b6cSCorey Minyard } 36*93198b6cSCorey Minyard data = i2c_recv(bus); 37*93198b6cSCorey Minyard i2c_nack(bus); 38*93198b6cSCorey Minyard i2c_end_transfer(bus); 39*93198b6cSCorey Minyard return data; 40*93198b6cSCorey Minyard } 41*93198b6cSCorey Minyard 42*93198b6cSCorey Minyard int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data) 43*93198b6cSCorey Minyard { 44*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, 0)) { 45*93198b6cSCorey Minyard return -1; 46*93198b6cSCorey Minyard } 47*93198b6cSCorey Minyard i2c_send(bus, data); 48*93198b6cSCorey Minyard i2c_end_transfer(bus); 49*93198b6cSCorey Minyard return 0; 50*93198b6cSCorey Minyard } 51*93198b6cSCorey Minyard 52*93198b6cSCorey Minyard int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command) 53*93198b6cSCorey Minyard { 54*93198b6cSCorey Minyard uint8_t data; 55*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, 0)) { 56*93198b6cSCorey Minyard return -1; 57*93198b6cSCorey Minyard } 58*93198b6cSCorey Minyard i2c_send(bus, command); 59*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, 1)) { 60*93198b6cSCorey Minyard i2c_end_transfer(bus); 61*93198b6cSCorey Minyard return -1; 62*93198b6cSCorey Minyard } 63*93198b6cSCorey Minyard data = i2c_recv(bus); 64*93198b6cSCorey Minyard i2c_nack(bus); 65*93198b6cSCorey Minyard i2c_end_transfer(bus); 66*93198b6cSCorey Minyard return data; 67*93198b6cSCorey Minyard } 68*93198b6cSCorey Minyard 69*93198b6cSCorey Minyard int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data) 70*93198b6cSCorey Minyard { 71*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, 0)) { 72*93198b6cSCorey Minyard return -1; 73*93198b6cSCorey Minyard } 74*93198b6cSCorey Minyard i2c_send(bus, command); 75*93198b6cSCorey Minyard i2c_send(bus, data); 76*93198b6cSCorey Minyard i2c_end_transfer(bus); 77*93198b6cSCorey Minyard return 0; 78*93198b6cSCorey Minyard } 79*93198b6cSCorey Minyard 80*93198b6cSCorey Minyard int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command) 81*93198b6cSCorey Minyard { 82*93198b6cSCorey Minyard uint16_t data; 83*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, 0)) { 84*93198b6cSCorey Minyard return -1; 85*93198b6cSCorey Minyard } 86*93198b6cSCorey Minyard i2c_send(bus, command); 87*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, 1)) { 88*93198b6cSCorey Minyard i2c_end_transfer(bus); 89*93198b6cSCorey Minyard return -1; 90*93198b6cSCorey Minyard } 91*93198b6cSCorey Minyard data = i2c_recv(bus); 92*93198b6cSCorey Minyard data |= i2c_recv(bus) << 8; 93*93198b6cSCorey Minyard i2c_nack(bus); 94*93198b6cSCorey Minyard i2c_end_transfer(bus); 95*93198b6cSCorey Minyard return data; 96*93198b6cSCorey Minyard } 97*93198b6cSCorey Minyard 98*93198b6cSCorey Minyard int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data) 99*93198b6cSCorey Minyard { 100*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, 0)) { 101*93198b6cSCorey Minyard return -1; 102*93198b6cSCorey Minyard } 103*93198b6cSCorey Minyard i2c_send(bus, command); 104*93198b6cSCorey Minyard i2c_send(bus, data & 0xff); 105*93198b6cSCorey Minyard i2c_send(bus, data >> 8); 106*93198b6cSCorey Minyard i2c_end_transfer(bus); 107*93198b6cSCorey Minyard return 0; 108*93198b6cSCorey Minyard } 109*93198b6cSCorey Minyard 110*93198b6cSCorey Minyard int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, 111*93198b6cSCorey Minyard int len, bool recv_len, bool send_cmd) 112*93198b6cSCorey Minyard { 113*93198b6cSCorey Minyard int rlen; 114*93198b6cSCorey Minyard int i; 115*93198b6cSCorey Minyard 116*93198b6cSCorey Minyard if (send_cmd) { 117*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, 0)) { 118*93198b6cSCorey Minyard return -1; 119*93198b6cSCorey Minyard } 120*93198b6cSCorey Minyard i2c_send(bus, command); 121*93198b6cSCorey Minyard } 122*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, 1)) { 123*93198b6cSCorey Minyard if (send_cmd) { 124*93198b6cSCorey Minyard i2c_end_transfer(bus); 125*93198b6cSCorey Minyard } 126*93198b6cSCorey Minyard return -1; 127*93198b6cSCorey Minyard } 128*93198b6cSCorey Minyard if (recv_len) { 129*93198b6cSCorey Minyard rlen = i2c_recv(bus); 130*93198b6cSCorey Minyard } else { 131*93198b6cSCorey Minyard rlen = len; 132*93198b6cSCorey Minyard } 133*93198b6cSCorey Minyard if (rlen > len) { 134*93198b6cSCorey Minyard rlen = 0; 135*93198b6cSCorey Minyard } 136*93198b6cSCorey Minyard for (i = 0; i < rlen; i++) { 137*93198b6cSCorey Minyard data[i] = i2c_recv(bus); 138*93198b6cSCorey Minyard } 139*93198b6cSCorey Minyard i2c_nack(bus); 140*93198b6cSCorey Minyard i2c_end_transfer(bus); 141*93198b6cSCorey Minyard return rlen; 142*93198b6cSCorey Minyard } 143*93198b6cSCorey Minyard 144*93198b6cSCorey Minyard int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, 145*93198b6cSCorey Minyard int len, bool send_len) 146*93198b6cSCorey Minyard { 147*93198b6cSCorey Minyard int i; 148*93198b6cSCorey Minyard 149*93198b6cSCorey Minyard if (len > 32) { 150*93198b6cSCorey Minyard len = 32; 151*93198b6cSCorey Minyard } 152*93198b6cSCorey Minyard 153*93198b6cSCorey Minyard if (i2c_start_transfer(bus, addr, 0)) { 154*93198b6cSCorey Minyard return -1; 155*93198b6cSCorey Minyard } 156*93198b6cSCorey Minyard i2c_send(bus, command); 157*93198b6cSCorey Minyard if (send_len) { 158*93198b6cSCorey Minyard i2c_send(bus, len); 159*93198b6cSCorey Minyard } 160*93198b6cSCorey Minyard for (i = 0; i < len; i++) { 161*93198b6cSCorey Minyard i2c_send(bus, data[i]); 162*93198b6cSCorey Minyard } 163*93198b6cSCorey Minyard i2c_end_transfer(bus); 164*93198b6cSCorey Minyard return 0; 165*93198b6cSCorey Minyard } 166