| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * PC SMBus implementation | 
					
						
							|  |  |  |  * splitted from acpi.c | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2006 Fabrice Bellard | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							| 
									
										
										
										
											2020-10-23 12:44:24 +00:00
										 |  |  |  * License version 2.1 as published by the Free Software Foundation. | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							| 
									
										
										
										
											2010-05-15 17:52:49 +00:00
										 |  |  |  * License along with this library; if not, see | 
					
						
							|  |  |  |  * <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 18:17:03 +00:00
										 |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-22 12:28:23 -06:00
										 |  |  | #include "hw/boards.h"
 | 
					
						
							| 
									
										
										
										
											2013-02-05 17:06:20 +01:00
										 |  |  | #include "hw/i2c/pm_smbus.h"
 | 
					
						
							| 
									
										
										
										
											2018-11-13 18:31:27 -06:00
										 |  |  | #include "hw/i2c/smbus_master.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:45 +02:00
										 |  |  | #include "migration/vmstate.h"
 | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define SMBHSTSTS       0x00
 | 
					
						
							|  |  |  | #define SMBHSTCNT       0x02
 | 
					
						
							|  |  |  | #define SMBHSTCMD       0x03
 | 
					
						
							|  |  |  | #define SMBHSTADD       0x04
 | 
					
						
							|  |  |  | #define SMBHSTDAT0      0x05
 | 
					
						
							|  |  |  | #define SMBHSTDAT1      0x06
 | 
					
						
							|  |  |  | #define SMBBLKDAT       0x07
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  | #define SMBAUXCTL       0x0d
 | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  | #define STS_HOST_BUSY   (1 << 0)
 | 
					
						
							|  |  |  | #define STS_INTR        (1 << 1)
 | 
					
						
							|  |  |  | #define STS_DEV_ERR     (1 << 2)
 | 
					
						
							|  |  |  | #define STS_BUS_ERR     (1 << 3)
 | 
					
						
							|  |  |  | #define STS_FAILED      (1 << 4)
 | 
					
						
							|  |  |  | #define STS_SMBALERT    (1 << 5)
 | 
					
						
							|  |  |  | #define STS_INUSE_STS   (1 << 6)
 | 
					
						
							|  |  |  | #define STS_BYTE_DONE   (1 << 7)
 | 
					
						
							| 
									
										
										
										
											2013-07-08 01:03:02 +04:00
										 |  |  | /* Signs of successfully transaction end :
 | 
					
						
							|  |  |  | *  ByteDoneStatus = 1 (STS_BYTE_DONE) and INTR = 1 (STS_INTR ) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  | #define CTL_INTREN      (1 << 0)
 | 
					
						
							|  |  |  | #define CTL_KILL        (1 << 1)
 | 
					
						
							|  |  |  | #define CTL_LAST_BYTE   (1 << 5)
 | 
					
						
							|  |  |  | #define CTL_START       (1 << 6)
 | 
					
						
							|  |  |  | #define CTL_PEC_EN      (1 << 7)
 | 
					
						
							|  |  |  | #define CTL_RETURN_MASK 0x1f
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define PROT_QUICK          0
 | 
					
						
							|  |  |  | #define PROT_BYTE           1
 | 
					
						
							|  |  |  | #define PROT_BYTE_DATA      2
 | 
					
						
							|  |  |  | #define PROT_WORD_DATA      3
 | 
					
						
							|  |  |  | #define PROT_PROC_CALL      4
 | 
					
						
							|  |  |  | #define PROT_BLOCK_DATA     5
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:03 -05:00
										 |  |  | #define PROT_I2C_BLOCK_READ 6
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  | #define AUX_PEC       (1 << 0)
 | 
					
						
							|  |  |  | #define AUX_BLK       (1 << 1)
 | 
					
						
							|  |  |  | #define AUX_MASK      0x3
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  | /*#define DEBUG*/ | 
					
						
							| 
									
										
										
										
											2010-05-14 16:29:21 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | # define SMBUS_DPRINTF(format, ...)     printf(format, ## __VA_ARGS__)
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | # define SMBUS_DPRINTF(format, ...)     do { } while (0)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  | static void smb_transaction(PMSMBus *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint8_t prot = (s->smb_ctl >> 2) & 0x07; | 
					
						
							|  |  |  |     uint8_t read = s->smb_addr & 0x01; | 
					
						
							|  |  |  |     uint8_t cmd = s->smb_cmd; | 
					
						
							|  |  |  |     uint8_t addr = s->smb_addr >> 1; | 
					
						
							| 
									
										
										
										
											2013-08-03 00:18:51 +02:00
										 |  |  |     I2CBus *bus = s->smbus; | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-14 16:29:21 +09:00
										 |  |  |     SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot); | 
					
						
							| 
									
										
										
										
											2013-07-08 01:03:02 +04:00
										 |  |  |     /* Transaction isn't exec if STS_DEV_ERR bit set */ | 
					
						
							|  |  |  |     if ((s->smb_stat & STS_DEV_ERR) != 0)  { | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |     switch(prot) { | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  |     case PROT_QUICK: | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  |         ret = smbus_quick_command(bus, addr, read); | 
					
						
							|  |  |  |         goto done; | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  |     case PROT_BYTE: | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         if (read) { | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  |             ret = smbus_receive_byte(bus, addr); | 
					
						
							|  |  |  |             goto data8; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  |             ret = smbus_send_byte(bus, addr, cmd); | 
					
						
							|  |  |  |             goto done; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  |     case PROT_BYTE_DATA: | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         if (read) { | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  |             ret = smbus_read_byte(bus, addr, cmd); | 
					
						
							|  |  |  |             goto data8; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  |             ret = smbus_write_byte(bus, addr, cmd, s->smb_data0); | 
					
						
							|  |  |  |             goto done; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  |     case PROT_WORD_DATA: | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         if (read) { | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  |             ret = smbus_read_word(bus, addr, cmd); | 
					
						
							|  |  |  |             goto data16; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  |             ret = smbus_write_word(bus, addr, cmd, | 
					
						
							|  |  |  |                                    (s->smb_data1 << 8) | s->smb_data0); | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  |             goto done; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:03 -05:00
										 |  |  |     case PROT_I2C_BLOCK_READ: | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |         /* According to the Linux i2c-i801 driver:
 | 
					
						
							|  |  |  |          *   NB: page 240 of ICH5 datasheet shows that the R/#W | 
					
						
							|  |  |  |          *   bit should be cleared here, even when reading. | 
					
						
							|  |  |  |          *   However if SPD Write Disable is set (Lynx Point and later), | 
					
						
							|  |  |  |          *   the read will fail if we don't set the R/#W bit. | 
					
						
							|  |  |  |          * So at least Linux may or may not set the read bit here. | 
					
						
							|  |  |  |          * So just ignore the read bit for this command. | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2021-06-17 13:53:34 +02:00
										 |  |  |         if (i2c_start_send(bus, addr)) { | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:03 -05:00
										 |  |  |             goto error; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |         ret = i2c_send(bus, s->smb_data1); | 
					
						
							|  |  |  |         if (ret) { | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-06-17 13:53:34 +02:00
										 |  |  |         if (i2c_start_recv(bus, addr)) { | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         s->in_i2c_block_read = true; | 
					
						
							|  |  |  |         s->smb_blkdata = i2c_recv(s->smbus); | 
					
						
							|  |  |  |         s->op_done = false; | 
					
						
							|  |  |  |         s->smb_stat |= STS_HOST_BUSY | STS_BYTE_DONE; | 
					
						
							|  |  |  |         goto out; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |     case PROT_BLOCK_DATA: | 
					
						
							|  |  |  |         if (read) { | 
					
						
							|  |  |  |             ret = smbus_read_block(bus, addr, cmd, s->smb_data, | 
					
						
							|  |  |  |                                    sizeof(s->smb_data), !s->i2c_enable, | 
					
						
							|  |  |  |                                    !s->i2c_enable); | 
					
						
							|  |  |  |             if (ret < 0) { | 
					
						
							|  |  |  |                 goto error; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             s->smb_index = 0; | 
					
						
							|  |  |  |             s->op_done = false; | 
					
						
							|  |  |  |             if (s->smb_auxctl & AUX_BLK) { | 
					
						
							|  |  |  |                 s->smb_stat |= STS_INTR; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 s->smb_blkdata = s->smb_data[0]; | 
					
						
							|  |  |  |                 s->smb_stat |= STS_HOST_BUSY | STS_BYTE_DONE; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             s->smb_data0 = ret; | 
					
						
							|  |  |  |             goto out; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (s->smb_auxctl & AUX_BLK) { | 
					
						
							|  |  |  |                 if (s->smb_index != s->smb_data0) { | 
					
						
							|  |  |  |                     s->smb_index = 0; | 
					
						
							|  |  |  |                     goto error; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 /* Data is already all written to the queue, just do
 | 
					
						
							|  |  |  |                    the operation. */ | 
					
						
							|  |  |  |                 s->smb_index = 0; | 
					
						
							|  |  |  |                 ret = smbus_write_block(bus, addr, cmd, s->smb_data, | 
					
						
							|  |  |  |                                         s->smb_data0, !s->i2c_enable); | 
					
						
							|  |  |  |                 if (ret < 0) { | 
					
						
							|  |  |  |                     goto error; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 s->op_done = true; | 
					
						
							|  |  |  |                 s->smb_stat |= STS_INTR; | 
					
						
							|  |  |  |                 s->smb_stat &= ~STS_HOST_BUSY; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 s->op_done = false; | 
					
						
							|  |  |  |                 s->smb_stat |= STS_HOST_BUSY | STS_BYTE_DONE; | 
					
						
							|  |  |  |                 s->smb_data[0] = s->smb_blkdata; | 
					
						
							|  |  |  |                 s->smb_index = 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             goto out; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |     default: | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  |     abort(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | data16: | 
					
						
							|  |  |  |     if (ret < 0) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     s->smb_data1 = ret >> 8; | 
					
						
							|  |  |  | data8: | 
					
						
							|  |  |  |     if (ret < 0) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     s->smb_data0 = ret; | 
					
						
							|  |  |  | done: | 
					
						
							|  |  |  |     if (ret < 0) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |     s->smb_stat |= STS_INTR; | 
					
						
							|  |  |  | out: | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  | error: | 
					
						
							| 
									
										
										
										
											2013-07-08 01:03:02 +04:00
										 |  |  |     s->smb_stat |= STS_DEV_ERR; | 
					
						
							| 
									
										
										
										
											2014-03-31 18:26:31 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-10 18:27:03 +01:00
										 |  |  | static void smb_transaction_start(PMSMBus *s) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:07 -05:00
										 |  |  |     if (s->smb_ctl & CTL_INTREN) { | 
					
						
							|  |  |  |         smb_transaction(s); | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |         s->start_transaction_on_status_read = false; | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:07 -05:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         /* Do not execute immediately the command; it will be
 | 
					
						
							|  |  |  |          * executed when guest will read SMB_STAT register.  This | 
					
						
							|  |  |  |          * is to work around a bug in AMIBIOS (that is working | 
					
						
							|  |  |  |          * around another bug in some specific hardware) where | 
					
						
							|  |  |  |          * it waits for STS_HOST_BUSY to be set before waiting | 
					
						
							|  |  |  |          * checking for status.  If STS_HOST_BUSY doesn't get | 
					
						
							|  |  |  |          * set, it gets stuck. */ | 
					
						
							|  |  |  |         s->smb_stat |= STS_HOST_BUSY; | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |         s->start_transaction_on_status_read = true; | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:07 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-12-10 18:27:03 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:06 -05:00
										 |  |  | static bool | 
					
						
							|  |  |  | smb_irq_value(PMSMBus *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return ((s->smb_stat & ~STS_HOST_BUSY) != 0) && (s->smb_ctl & CTL_INTREN); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  | static bool | 
					
						
							|  |  |  | smb_byte_by_byte(PMSMBus *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (s->op_done) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (s->in_i2c_block_read) { | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return !(s->smb_auxctl & AUX_BLK); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-23 14:57:01 +01:00
										 |  |  | static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val, | 
					
						
							|  |  |  |                               unsigned width) | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  | { | 
					
						
							|  |  |  |     PMSMBus *s = opaque; | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |     uint8_t clear_byte_done; | 
					
						
							| 
									
										
										
										
											2012-11-23 14:57:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Fix debug print warning
Steps:
1.enable qemu debug print, using simply scprit as below:
 grep "//#define DEBUG" * -rl | xargs sed -i "s/\/\/#define DEBUG/#define DEBUG/g"
2. make -j
3. get some warning:
hw/i2c/pm_smbus.c: In function 'smb_ioport_writeb':
hw/i2c/pm_smbus.c:142: warning: format '%04x' expects type 'unsigned int', but argument 2 has type 'hwaddr'
hw/i2c/pm_smbus.c:142: warning: format '%02x' expects type 'unsigned int', but argument 3 has type 'uint64_t'
hw/i2c/pm_smbus.c: In function 'smb_ioport_readb':
hw/i2c/pm_smbus.c:209: warning: format '%04x' expects type 'unsigned int', but argument 2 has type 'hwaddr'
hw/intc/i8259.c: In function 'pic_ioport_read':
hw/intc/i8259.c:373: warning: format '%02x' expects type 'unsigned int', but argument 2 has type 'hwaddr'
hw/input/pckbd.c: In function 'kbd_write_command':
hw/input/pckbd.c:232: warning: format '%02x' expects type 'unsigned int', but argument 2 has type 'uint64_t'
hw/input/pckbd.c: In function 'kbd_write_data':
hw/input/pckbd.c:333: warning: format '%02x' expects type 'unsigned int', but argument 2 has type 'uint64_t'
hw/isa/apm.c: In function 'apm_ioport_writeb':
hw/isa/apm.c:44: warning: format '%x' expects type 'unsigned int', but argument 2 has type 'hwaddr'
hw/isa/apm.c:44: warning: format '%02x' expects type 'unsigned int', but argument 3 has type 'uint64_t'
hw/isa/apm.c: In function 'apm_ioport_readb':
hw/isa/apm.c:67: warning: format '%x' expects type 'unsigned int', but argument 2 has type 'hwaddr'
hw/timer/mc146818rtc.c: In function 'cmos_ioport_write':
hw/timer/mc146818rtc.c:394: warning: format '%02x' expects type 'unsigned int', but argument 3 has type 'uint64_t'
hw/i386/pc.c: In function 'port92_write':
hw/i386/pc.c:479: warning: format '%02x' expects type 'unsigned int', but argument 2 has type 'uint64_t'
Fix them.
Cc: qemu-trivial@nongnu.org
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
											
										 
											2014-08-25 10:01:27 +08:00
										 |  |  |     SMBUS_DPRINTF("SMB writeb port=0x%04" HWADDR_PRIx | 
					
						
							|  |  |  |                   " val=0x%02" PRIx64 "\n", addr, val); | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |     switch(addr) { | 
					
						
							|  |  |  |     case SMBHSTSTS: | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |         clear_byte_done = s->smb_stat & val & STS_BYTE_DONE; | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |         s->smb_stat &= ~(val & ~STS_HOST_BUSY); | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |         if (clear_byte_done && smb_byte_by_byte(s)) { | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |             uint8_t read = s->smb_addr & 0x01; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |             if (s->in_i2c_block_read) { | 
					
						
							|  |  |  |                 /* See comment below PROT_I2C_BLOCK_READ above. */ | 
					
						
							|  |  |  |                 read = 1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |             s->smb_index++; | 
					
						
							| 
									
										
										
										
											2018-12-06 17:48:30 +05:30
										 |  |  |             if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) { | 
					
						
							|  |  |  |                 s->smb_index = 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |             if (!read && s->smb_index == s->smb_data0) { | 
					
						
							|  |  |  |                 uint8_t prot = (s->smb_ctl >> 2) & 0x07; | 
					
						
							|  |  |  |                 uint8_t cmd = s->smb_cmd; | 
					
						
							|  |  |  |                 uint8_t addr = s->smb_addr >> 1; | 
					
						
							|  |  |  |                 int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (prot == PROT_I2C_BLOCK_READ) { | 
					
						
							|  |  |  |                     s->smb_stat |= STS_DEV_ERR; | 
					
						
							|  |  |  |                     goto out; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 ret = smbus_write_block(s->smbus, addr, cmd, s->smb_data, | 
					
						
							|  |  |  |                                         s->smb_data0, !s->i2c_enable); | 
					
						
							|  |  |  |                 if (ret < 0) { | 
					
						
							|  |  |  |                     s->smb_stat |= STS_DEV_ERR; | 
					
						
							|  |  |  |                     goto out; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 s->op_done = true; | 
					
						
							|  |  |  |                 s->smb_stat |= STS_INTR; | 
					
						
							|  |  |  |                 s->smb_stat &= ~STS_HOST_BUSY; | 
					
						
							|  |  |  |             } else if (!read) { | 
					
						
							|  |  |  |                 s->smb_data[s->smb_index] = s->smb_blkdata; | 
					
						
							|  |  |  |                 s->smb_stat |= STS_BYTE_DONE; | 
					
						
							|  |  |  |             } else if (s->smb_ctl & CTL_LAST_BYTE) { | 
					
						
							|  |  |  |                 s->op_done = true; | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |                 if (s->in_i2c_block_read) { | 
					
						
							|  |  |  |                     s->in_i2c_block_read = false; | 
					
						
							|  |  |  |                     s->smb_blkdata = i2c_recv(s->smbus); | 
					
						
							|  |  |  |                     i2c_nack(s->smbus); | 
					
						
							|  |  |  |                     i2c_end_transfer(s->smbus); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     s->smb_blkdata = s->smb_data[s->smb_index]; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |                 s->smb_index = 0; | 
					
						
							|  |  |  |                 s->smb_stat |= STS_INTR; | 
					
						
							|  |  |  |                 s->smb_stat &= ~STS_HOST_BUSY; | 
					
						
							|  |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |                 if (s->in_i2c_block_read) { | 
					
						
							|  |  |  |                     s->smb_blkdata = i2c_recv(s->smbus); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     s->smb_blkdata = s->smb_data[s->smb_index]; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |                 s->smb_stat |= STS_BYTE_DONE; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case SMBHSTCNT: | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |         s->smb_ctl = val & ~CTL_START; /* CTL_START always reads 0 */ | 
					
						
							|  |  |  |         if (val & CTL_START) { | 
					
						
							|  |  |  |             if (!s->op_done) { | 
					
						
							|  |  |  |                 s->smb_index = 0; | 
					
						
							|  |  |  |                 s->op_done = true; | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |                 if (s->in_i2c_block_read) { | 
					
						
							|  |  |  |                     s->in_i2c_block_read = false; | 
					
						
							|  |  |  |                     i2c_end_transfer(s->smbus); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-12-10 18:27:03 +01:00
										 |  |  |             smb_transaction_start(s); | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |         if (s->smb_ctl & CTL_KILL) { | 
					
						
							|  |  |  |             s->op_done = true; | 
					
						
							|  |  |  |             s->smb_index = 0; | 
					
						
							|  |  |  |             s->smb_stat |= STS_FAILED; | 
					
						
							|  |  |  |             s->smb_stat &= ~STS_HOST_BUSY; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case SMBHSTCMD: | 
					
						
							|  |  |  |         s->smb_cmd = val; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SMBHSTADD: | 
					
						
							|  |  |  |         s->smb_addr = val; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SMBHSTDAT0: | 
					
						
							|  |  |  |         s->smb_data0 = val; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SMBHSTDAT1: | 
					
						
							|  |  |  |         s->smb_data1 = val; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SMBBLKDAT: | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |         if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) { | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |             s->smb_index = 0; | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (s->smb_auxctl & AUX_BLK) { | 
					
						
							|  |  |  |             s->smb_data[s->smb_index++] = val; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             s->smb_blkdata = val; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SMBAUXCTL: | 
					
						
							|  |  |  |         s->smb_auxctl = val & AUX_MASK; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |  out: | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:06 -05:00
										 |  |  |     if (s->set_irq) { | 
					
						
							|  |  |  |         s->set_irq(s, smb_irq_value(s)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-23 14:57:01 +01:00
										 |  |  | static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width) | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  | { | 
					
						
							|  |  |  |     PMSMBus *s = opaque; | 
					
						
							|  |  |  |     uint32_t val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch(addr) { | 
					
						
							|  |  |  |     case SMBHSTSTS: | 
					
						
							|  |  |  |         val = s->smb_stat; | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |         if (s->start_transaction_on_status_read) { | 
					
						
							| 
									
										
										
										
											2017-12-10 18:27:03 +01:00
										 |  |  |             /* execute command now */ | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |             s->start_transaction_on_status_read = false; | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:07 -05:00
										 |  |  |             s->smb_stat &= ~STS_HOST_BUSY; | 
					
						
							| 
									
										
										
										
											2017-12-10 18:27:03 +01:00
										 |  |  |             smb_transaction(s); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case SMBHSTCNT: | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  |         val = s->smb_ctl & CTL_RETURN_MASK; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case SMBHSTCMD: | 
					
						
							|  |  |  |         val = s->smb_cmd; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SMBHSTADD: | 
					
						
							|  |  |  |         val = s->smb_addr; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SMBHSTDAT0: | 
					
						
							|  |  |  |         val = s->smb_data0; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SMBHSTDAT1: | 
					
						
							|  |  |  |         val = s->smb_data1; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SMBBLKDAT: | 
					
						
							| 
									
										
										
										
											2018-11-14 14:41:01 -06:00
										 |  |  |         if (s->smb_auxctl & AUX_BLK && !s->in_i2c_block_read) { | 
					
						
							|  |  |  |             if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) { | 
					
						
							|  |  |  |                 s->smb_index = 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |             val = s->smb_data[s->smb_index++]; | 
					
						
							|  |  |  |             if (!s->op_done && s->smb_index == s->smb_data0) { | 
					
						
							|  |  |  |                 s->op_done = true; | 
					
						
							|  |  |  |                 s->smb_index = 0; | 
					
						
							|  |  |  |                 s->smb_stat &= ~STS_HOST_BUSY; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             val = s->smb_blkdata; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SMBAUXCTL: | 
					
						
							|  |  |  |         val = s->smb_auxctl; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         val = 0; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:01 -05:00
										 |  |  |     SMBUS_DPRINTF("SMB readb port=0x%04" HWADDR_PRIx " val=0x%02x\n", | 
					
						
							|  |  |  |                   addr, val); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:06 -05:00
										 |  |  |     if (s->set_irq) { | 
					
						
							|  |  |  |         s->set_irq(s, smb_irq_value(s)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |     return val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  | static void pm_smbus_reset(PMSMBus *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     s->op_done = true; | 
					
						
							|  |  |  |     s->smb_index = 0; | 
					
						
							|  |  |  |     s->smb_stat = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-23 14:57:01 +01:00
										 |  |  | static const MemoryRegionOps pm_smbus_ops = { | 
					
						
							|  |  |  |     .read = smb_ioport_readb, | 
					
						
							|  |  |  |     .write = smb_ioport_writeb, | 
					
						
							|  |  |  |     .valid.min_access_size = 1, | 
					
						
							|  |  |  |     .valid.max_access_size = 1, | 
					
						
							|  |  |  |     .endianness = DEVICE_LITTLE_ENDIAN, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-22 12:28:23 -06:00
										 |  |  | bool pm_smbus_vmstate_needed(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return !mc->smbus_no_migration_support; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const VMStateDescription pmsmb_vmstate = { | 
					
						
							|  |  |  |     .name = "pmsmb", | 
					
						
							|  |  |  |     .version_id = 1, | 
					
						
							|  |  |  |     .minimum_version_id = 1, | 
					
						
							|  |  |  |     .fields = (VMStateField[]) { | 
					
						
							|  |  |  |         VMSTATE_UINT8(smb_stat, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_UINT8(smb_ctl, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_UINT8(smb_cmd, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_UINT8(smb_addr, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_UINT8(smb_data0, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_UINT8(smb_data1, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_UINT32(smb_index, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_UINT8_ARRAY(smb_data, PMSMBus, PM_SMBUS_MAX_MSG_SIZE), | 
					
						
							|  |  |  |         VMSTATE_UINT8(smb_auxctl, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_UINT8(smb_blkdata, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_BOOL(i2c_enable, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_BOOL(op_done, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_BOOL(in_i2c_block_read, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_BOOL(start_transaction_on_status_read, PMSMBus), | 
					
						
							|  |  |  |         VMSTATE_END_OF_LIST() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:08 -05:00
										 |  |  | void pm_smbus_init(DeviceState *parent, PMSMBus *smb, bool force_aux_blk) | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:04 -05:00
										 |  |  |     smb->op_done = true; | 
					
						
							|  |  |  |     smb->reset = pm_smbus_reset; | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  |     smb->smbus = i2c_init_bus(parent, "i2c"); | 
					
						
							| 
									
										
										
										
											2018-08-20 15:26:08 -05:00
										 |  |  |     if (force_aux_blk) { | 
					
						
							|  |  |  |         smb->smb_auxctl |= AUX_BLK; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-06-06 21:25:08 -04:00
										 |  |  |     memory_region_init_io(&smb->io, OBJECT(parent), &pm_smbus_ops, smb, | 
					
						
							|  |  |  |                           "pm-smbus", 64); | 
					
						
							| 
									
										
										
										
											2010-05-14 16:28:59 +09:00
										 |  |  | } |