pm_smbus.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /*
  2. * PC SMBus implementation
  3. * splitted from acpi.c
  4. *
  5. * Copyright (c) 2006 Fabrice Bellard
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License version 2.1 as published by the Free Software Foundation.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #include "qemu/osdep.h"
  21. #include "hw/boards.h"
  22. #include "hw/i2c/pm_smbus.h"
  23. #include "hw/i2c/smbus_master.h"
  24. #include "migration/vmstate.h"
  25. #define SMBHSTSTS 0x00
  26. #define SMBHSTCNT 0x02
  27. #define SMBHSTCMD 0x03
  28. #define SMBHSTADD 0x04
  29. #define SMBHSTDAT0 0x05
  30. #define SMBHSTDAT1 0x06
  31. #define SMBBLKDAT 0x07
  32. #define SMBAUXCTL 0x0d
  33. #define STS_HOST_BUSY (1 << 0)
  34. #define STS_INTR (1 << 1)
  35. #define STS_DEV_ERR (1 << 2)
  36. #define STS_BUS_ERR (1 << 3)
  37. #define STS_FAILED (1 << 4)
  38. #define STS_SMBALERT (1 << 5)
  39. #define STS_INUSE_STS (1 << 6)
  40. #define STS_BYTE_DONE (1 << 7)
  41. /* Signs of successfully transaction end :
  42. * ByteDoneStatus = 1 (STS_BYTE_DONE) and INTR = 1 (STS_INTR )
  43. */
  44. #define CTL_INTREN (1 << 0)
  45. #define CTL_KILL (1 << 1)
  46. #define CTL_LAST_BYTE (1 << 5)
  47. #define CTL_START (1 << 6)
  48. #define CTL_PEC_EN (1 << 7)
  49. #define CTL_RETURN_MASK 0x1f
  50. #define PROT_QUICK 0
  51. #define PROT_BYTE 1
  52. #define PROT_BYTE_DATA 2
  53. #define PROT_WORD_DATA 3
  54. #define PROT_PROC_CALL 4
  55. #define PROT_BLOCK_DATA 5
  56. #define PROT_I2C_BLOCK_READ 6
  57. #define AUX_PEC (1 << 0)
  58. #define AUX_BLK (1 << 1)
  59. #define AUX_MASK 0x3
  60. /*#define DEBUG*/
  61. #ifdef DEBUG
  62. # define SMBUS_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
  63. #else
  64. # define SMBUS_DPRINTF(format, ...) do { } while (0)
  65. #endif
  66. static void smb_transaction(PMSMBus *s)
  67. {
  68. uint8_t prot = (s->smb_ctl >> 2) & 0x07;
  69. uint8_t read = s->smb_addr & 0x01;
  70. uint8_t cmd = s->smb_cmd;
  71. uint8_t addr = s->smb_addr >> 1;
  72. I2CBus *bus = s->smbus;
  73. int ret;
  74. SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
  75. /* Transaction isn't exec if STS_DEV_ERR bit set */
  76. if ((s->smb_stat & STS_DEV_ERR) != 0) {
  77. goto error;
  78. }
  79. switch(prot) {
  80. case PROT_QUICK:
  81. ret = smbus_quick_command(bus, addr, read);
  82. goto done;
  83. case PROT_BYTE:
  84. if (read) {
  85. ret = smbus_receive_byte(bus, addr);
  86. goto data8;
  87. } else {
  88. ret = smbus_send_byte(bus, addr, cmd);
  89. goto done;
  90. }
  91. case PROT_BYTE_DATA:
  92. if (read) {
  93. ret = smbus_read_byte(bus, addr, cmd);
  94. goto data8;
  95. } else {
  96. ret = smbus_write_byte(bus, addr, cmd, s->smb_data0);
  97. goto done;
  98. }
  99. break;
  100. case PROT_WORD_DATA:
  101. if (read) {
  102. ret = smbus_read_word(bus, addr, cmd);
  103. goto data16;
  104. } else {
  105. ret = smbus_write_word(bus, addr, cmd,
  106. (s->smb_data1 << 8) | s->smb_data0);
  107. goto done;
  108. }
  109. break;
  110. case PROT_I2C_BLOCK_READ:
  111. /* According to the Linux i2c-i801 driver:
  112. * NB: page 240 of ICH5 datasheet shows that the R/#W
  113. * bit should be cleared here, even when reading.
  114. * However if SPD Write Disable is set (Lynx Point and later),
  115. * the read will fail if we don't set the R/#W bit.
  116. * So at least Linux may or may not set the read bit here.
  117. * So just ignore the read bit for this command.
  118. */
  119. if (i2c_start_send(bus, addr)) {
  120. goto error;
  121. }
  122. ret = i2c_send(bus, s->smb_data1);
  123. if (ret) {
  124. goto error;
  125. }
  126. if (i2c_start_recv(bus, addr)) {
  127. goto error;
  128. }
  129. s->in_i2c_block_read = true;
  130. s->smb_blkdata = i2c_recv(s->smbus);
  131. s->op_done = false;
  132. s->smb_stat |= STS_HOST_BUSY | STS_BYTE_DONE;
  133. goto out;
  134. case PROT_BLOCK_DATA:
  135. if (read) {
  136. ret = smbus_read_block(bus, addr, cmd, s->smb_data,
  137. sizeof(s->smb_data), !s->i2c_enable,
  138. !s->i2c_enable);
  139. if (ret < 0) {
  140. goto error;
  141. }
  142. s->smb_index = 0;
  143. s->op_done = false;
  144. if (s->smb_auxctl & AUX_BLK) {
  145. s->smb_stat |= STS_INTR;
  146. } else {
  147. s->smb_blkdata = s->smb_data[0];
  148. s->smb_stat |= STS_HOST_BUSY | STS_BYTE_DONE;
  149. }
  150. s->smb_data0 = ret;
  151. goto out;
  152. } else {
  153. if (s->smb_auxctl & AUX_BLK) {
  154. if (s->smb_index != s->smb_data0) {
  155. s->smb_index = 0;
  156. goto error;
  157. }
  158. /* Data is already all written to the queue, just do
  159. the operation. */
  160. s->smb_index = 0;
  161. ret = smbus_write_block(bus, addr, cmd, s->smb_data,
  162. s->smb_data0, !s->i2c_enable);
  163. if (ret < 0) {
  164. goto error;
  165. }
  166. s->op_done = true;
  167. s->smb_stat |= STS_INTR;
  168. s->smb_stat &= ~STS_HOST_BUSY;
  169. } else {
  170. s->op_done = false;
  171. s->smb_stat |= STS_HOST_BUSY | STS_BYTE_DONE;
  172. s->smb_data[0] = s->smb_blkdata;
  173. s->smb_index = 0;
  174. }
  175. goto out;
  176. }
  177. break;
  178. default:
  179. goto error;
  180. }
  181. abort();
  182. data16:
  183. if (ret < 0) {
  184. goto error;
  185. }
  186. s->smb_data1 = ret >> 8;
  187. data8:
  188. if (ret < 0) {
  189. goto error;
  190. }
  191. s->smb_data0 = ret;
  192. done:
  193. if (ret < 0) {
  194. goto error;
  195. }
  196. s->smb_stat |= STS_INTR;
  197. out:
  198. return;
  199. error:
  200. s->smb_stat |= STS_DEV_ERR;
  201. return;
  202. }
  203. static void smb_transaction_start(PMSMBus *s)
  204. {
  205. if (s->smb_ctl & CTL_INTREN) {
  206. smb_transaction(s);
  207. s->start_transaction_on_status_read = false;
  208. } else {
  209. /* Do not execute immediately the command; it will be
  210. * executed when guest will read SMB_STAT register. This
  211. * is to work around a bug in AMIBIOS (that is working
  212. * around another bug in some specific hardware) where
  213. * it waits for STS_HOST_BUSY to be set before waiting
  214. * checking for status. If STS_HOST_BUSY doesn't get
  215. * set, it gets stuck. */
  216. s->smb_stat |= STS_HOST_BUSY;
  217. s->start_transaction_on_status_read = true;
  218. }
  219. }
  220. static bool
  221. smb_irq_value(PMSMBus *s)
  222. {
  223. return ((s->smb_stat & ~STS_HOST_BUSY) != 0) && (s->smb_ctl & CTL_INTREN);
  224. }
  225. static bool
  226. smb_byte_by_byte(PMSMBus *s)
  227. {
  228. if (s->op_done) {
  229. return false;
  230. }
  231. if (s->in_i2c_block_read) {
  232. return true;
  233. }
  234. return !(s->smb_auxctl & AUX_BLK);
  235. }
  236. static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
  237. unsigned width)
  238. {
  239. PMSMBus *s = opaque;
  240. uint8_t clear_byte_done;
  241. SMBUS_DPRINTF("SMB writeb port=0x%04" HWADDR_PRIx
  242. " val=0x%02" PRIx64 "\n", addr, val);
  243. switch(addr) {
  244. case SMBHSTSTS:
  245. clear_byte_done = s->smb_stat & val & STS_BYTE_DONE;
  246. s->smb_stat &= ~(val & ~STS_HOST_BUSY);
  247. if (clear_byte_done && smb_byte_by_byte(s)) {
  248. uint8_t read = s->smb_addr & 0x01;
  249. if (s->in_i2c_block_read) {
  250. /* See comment below PROT_I2C_BLOCK_READ above. */
  251. read = 1;
  252. }
  253. s->smb_index++;
  254. if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
  255. s->smb_index = 0;
  256. }
  257. if (!read && s->smb_index == s->smb_data0) {
  258. uint8_t prot = (s->smb_ctl >> 2) & 0x07;
  259. uint8_t cmd = s->smb_cmd;
  260. uint8_t addr = s->smb_addr >> 1;
  261. int ret;
  262. if (prot == PROT_I2C_BLOCK_READ) {
  263. s->smb_stat |= STS_DEV_ERR;
  264. goto out;
  265. }
  266. ret = smbus_write_block(s->smbus, addr, cmd, s->smb_data,
  267. s->smb_data0, !s->i2c_enable);
  268. if (ret < 0) {
  269. s->smb_stat |= STS_DEV_ERR;
  270. goto out;
  271. }
  272. s->op_done = true;
  273. s->smb_stat |= STS_INTR;
  274. s->smb_stat &= ~STS_HOST_BUSY;
  275. } else if (!read) {
  276. s->smb_data[s->smb_index] = s->smb_blkdata;
  277. s->smb_stat |= STS_BYTE_DONE;
  278. } else if (s->smb_ctl & CTL_LAST_BYTE) {
  279. s->op_done = true;
  280. if (s->in_i2c_block_read) {
  281. s->in_i2c_block_read = false;
  282. s->smb_blkdata = i2c_recv(s->smbus);
  283. i2c_nack(s->smbus);
  284. i2c_end_transfer(s->smbus);
  285. } else {
  286. s->smb_blkdata = s->smb_data[s->smb_index];
  287. }
  288. s->smb_index = 0;
  289. s->smb_stat |= STS_INTR;
  290. s->smb_stat &= ~STS_HOST_BUSY;
  291. } else {
  292. if (s->in_i2c_block_read) {
  293. s->smb_blkdata = i2c_recv(s->smbus);
  294. } else {
  295. s->smb_blkdata = s->smb_data[s->smb_index];
  296. }
  297. s->smb_stat |= STS_BYTE_DONE;
  298. }
  299. }
  300. break;
  301. case SMBHSTCNT:
  302. s->smb_ctl = val & ~CTL_START; /* CTL_START always reads 0 */
  303. if (val & CTL_START) {
  304. if (!s->op_done) {
  305. s->smb_index = 0;
  306. s->op_done = true;
  307. if (s->in_i2c_block_read) {
  308. s->in_i2c_block_read = false;
  309. i2c_end_transfer(s->smbus);
  310. }
  311. }
  312. smb_transaction_start(s);
  313. }
  314. if (s->smb_ctl & CTL_KILL) {
  315. s->op_done = true;
  316. s->smb_index = 0;
  317. s->smb_stat |= STS_FAILED;
  318. s->smb_stat &= ~STS_HOST_BUSY;
  319. }
  320. break;
  321. case SMBHSTCMD:
  322. s->smb_cmd = val;
  323. break;
  324. case SMBHSTADD:
  325. s->smb_addr = val;
  326. break;
  327. case SMBHSTDAT0:
  328. s->smb_data0 = val;
  329. break;
  330. case SMBHSTDAT1:
  331. s->smb_data1 = val;
  332. break;
  333. case SMBBLKDAT:
  334. if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
  335. s->smb_index = 0;
  336. }
  337. if (s->smb_auxctl & AUX_BLK) {
  338. s->smb_data[s->smb_index++] = val;
  339. } else {
  340. s->smb_blkdata = val;
  341. }
  342. break;
  343. case SMBAUXCTL:
  344. s->smb_auxctl = val & AUX_MASK;
  345. break;
  346. default:
  347. break;
  348. }
  349. out:
  350. if (s->set_irq) {
  351. s->set_irq(s, smb_irq_value(s));
  352. }
  353. }
  354. static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width)
  355. {
  356. PMSMBus *s = opaque;
  357. uint32_t val;
  358. switch(addr) {
  359. case SMBHSTSTS:
  360. val = s->smb_stat;
  361. if (s->start_transaction_on_status_read) {
  362. /* execute command now */
  363. s->start_transaction_on_status_read = false;
  364. s->smb_stat &= ~STS_HOST_BUSY;
  365. smb_transaction(s);
  366. }
  367. break;
  368. case SMBHSTCNT:
  369. val = s->smb_ctl & CTL_RETURN_MASK;
  370. break;
  371. case SMBHSTCMD:
  372. val = s->smb_cmd;
  373. break;
  374. case SMBHSTADD:
  375. val = s->smb_addr;
  376. break;
  377. case SMBHSTDAT0:
  378. val = s->smb_data0;
  379. break;
  380. case SMBHSTDAT1:
  381. val = s->smb_data1;
  382. break;
  383. case SMBBLKDAT:
  384. if (s->smb_auxctl & AUX_BLK && !s->in_i2c_block_read) {
  385. if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
  386. s->smb_index = 0;
  387. }
  388. val = s->smb_data[s->smb_index++];
  389. if (!s->op_done && s->smb_index == s->smb_data0) {
  390. s->op_done = true;
  391. s->smb_index = 0;
  392. s->smb_stat &= ~STS_HOST_BUSY;
  393. }
  394. } else {
  395. val = s->smb_blkdata;
  396. }
  397. break;
  398. case SMBAUXCTL:
  399. val = s->smb_auxctl;
  400. break;
  401. default:
  402. val = 0;
  403. break;
  404. }
  405. SMBUS_DPRINTF("SMB readb port=0x%04" HWADDR_PRIx " val=0x%02x\n",
  406. addr, val);
  407. if (s->set_irq) {
  408. s->set_irq(s, smb_irq_value(s));
  409. }
  410. return val;
  411. }
  412. static void pm_smbus_reset(PMSMBus *s)
  413. {
  414. s->op_done = true;
  415. s->smb_index = 0;
  416. s->smb_stat = 0;
  417. }
  418. static const MemoryRegionOps pm_smbus_ops = {
  419. .read = smb_ioport_readb,
  420. .write = smb_ioport_writeb,
  421. .valid.min_access_size = 1,
  422. .valid.max_access_size = 1,
  423. .endianness = DEVICE_LITTLE_ENDIAN,
  424. };
  425. bool pm_smbus_vmstate_needed(void)
  426. {
  427. MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
  428. return !mc->smbus_no_migration_support;
  429. }
  430. const VMStateDescription pmsmb_vmstate = {
  431. .name = "pmsmb",
  432. .version_id = 1,
  433. .minimum_version_id = 1,
  434. .fields = (VMStateField[]) {
  435. VMSTATE_UINT8(smb_stat, PMSMBus),
  436. VMSTATE_UINT8(smb_ctl, PMSMBus),
  437. VMSTATE_UINT8(smb_cmd, PMSMBus),
  438. VMSTATE_UINT8(smb_addr, PMSMBus),
  439. VMSTATE_UINT8(smb_data0, PMSMBus),
  440. VMSTATE_UINT8(smb_data1, PMSMBus),
  441. VMSTATE_UINT32(smb_index, PMSMBus),
  442. VMSTATE_UINT8_ARRAY(smb_data, PMSMBus, PM_SMBUS_MAX_MSG_SIZE),
  443. VMSTATE_UINT8(smb_auxctl, PMSMBus),
  444. VMSTATE_UINT8(smb_blkdata, PMSMBus),
  445. VMSTATE_BOOL(i2c_enable, PMSMBus),
  446. VMSTATE_BOOL(op_done, PMSMBus),
  447. VMSTATE_BOOL(in_i2c_block_read, PMSMBus),
  448. VMSTATE_BOOL(start_transaction_on_status_read, PMSMBus),
  449. VMSTATE_END_OF_LIST()
  450. }
  451. };
  452. void pm_smbus_init(DeviceState *parent, PMSMBus *smb, bool force_aux_blk)
  453. {
  454. smb->op_done = true;
  455. smb->reset = pm_smbus_reset;
  456. smb->smbus = i2c_init_bus(parent, "i2c");
  457. if (force_aux_blk) {
  458. smb->smb_auxctl |= AUX_BLK;
  459. }
  460. memory_region_init_io(&smb->io, OBJECT(parent), &pm_smbus_ops, smb,
  461. "pm-smbus", 64);
  462. }