qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

smbus_master.c (3437B)


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