pm_smbus.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  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 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_transfer(bus, addr, 0)) {
  120. goto error;
  121. }
  122. ret = i2c_send(bus, s->smb_data1);
  123. if (ret) {
  124. goto error;
  125. }
  126. if (i2c_start_transfer(bus, addr, 1)) {
  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. ret = 0;
  175. }
  176. goto out;
  177. }
  178. break;
  179. default:
  180. goto error;
  181. }
  182. abort();
  183. data16:
  184. if (ret < 0) {
  185. goto error;
  186. }
  187. s->smb_data1 = ret >> 8;
  188. data8:
  189. if (ret < 0) {
  190. goto error;
  191. }
  192. s->smb_data0 = ret;
  193. done:
  194. if (ret < 0) {
  195. goto error;
  196. }
  197. s->smb_stat |= STS_INTR;
  198. out:
  199. return;
  200. error:
  201. s->smb_stat |= STS_DEV_ERR;
  202. return;
  203. }
  204. static void smb_transaction_start(PMSMBus *s)
  205. {
  206. if (s->smb_ctl & CTL_INTREN) {
  207. smb_transaction(s);
  208. s->start_transaction_on_status_read = false;
  209. } else {
  210. /* Do not execute immediately the command; it will be
  211. * executed when guest will read SMB_STAT register. This
  212. * is to work around a bug in AMIBIOS (that is working
  213. * around another bug in some specific hardware) where
  214. * it waits for STS_HOST_BUSY to be set before waiting
  215. * checking for status. If STS_HOST_BUSY doesn't get
  216. * set, it gets stuck. */
  217. s->smb_stat |= STS_HOST_BUSY;
  218. s->start_transaction_on_status_read = true;
  219. }
  220. }
  221. static bool
  222. smb_irq_value(PMSMBus *s)
  223. {
  224. return ((s->smb_stat & ~STS_HOST_BUSY) != 0) && (s->smb_ctl & CTL_INTREN);
  225. }
  226. static bool
  227. smb_byte_by_byte(PMSMBus *s)
  228. {
  229. if (s->op_done) {
  230. return false;
  231. }
  232. if (s->in_i2c_block_read) {
  233. return true;
  234. }
  235. return !(s->smb_auxctl & AUX_BLK);
  236. }
  237. static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
  238. unsigned width)
  239. {
  240. PMSMBus *s = opaque;
  241. uint8_t clear_byte_done;
  242. SMBUS_DPRINTF("SMB writeb port=0x%04" HWADDR_PRIx
  243. " val=0x%02" PRIx64 "\n", addr, val);
  244. switch(addr) {
  245. case SMBHSTSTS:
  246. clear_byte_done = s->smb_stat & val & STS_BYTE_DONE;
  247. s->smb_stat &= ~(val & ~STS_HOST_BUSY);
  248. if (clear_byte_done && smb_byte_by_byte(s)) {
  249. uint8_t read = s->smb_addr & 0x01;
  250. if (s->in_i2c_block_read) {
  251. /* See comment below PROT_I2C_BLOCK_READ above. */
  252. read = 1;
  253. }
  254. s->smb_index++;
  255. if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
  256. s->smb_index = 0;
  257. }
  258. if (!read && s->smb_index == s->smb_data0) {
  259. uint8_t prot = (s->smb_ctl >> 2) & 0x07;
  260. uint8_t cmd = s->smb_cmd;
  261. uint8_t addr = s->smb_addr >> 1;
  262. int ret;
  263. if (prot == PROT_I2C_BLOCK_READ) {
  264. s->smb_stat |= STS_DEV_ERR;
  265. goto out;
  266. }
  267. ret = smbus_write_block(s->smbus, addr, cmd, s->smb_data,
  268. s->smb_data0, !s->i2c_enable);
  269. if (ret < 0) {
  270. s->smb_stat |= STS_DEV_ERR;
  271. goto out;
  272. }
  273. s->op_done = true;
  274. s->smb_stat |= STS_INTR;
  275. s->smb_stat &= ~STS_HOST_BUSY;
  276. } else if (!read) {
  277. s->smb_data[s->smb_index] = s->smb_blkdata;
  278. s->smb_stat |= STS_BYTE_DONE;
  279. } else if (s->smb_ctl & CTL_LAST_BYTE) {
  280. s->op_done = true;
  281. if (s->in_i2c_block_read) {
  282. s->in_i2c_block_read = false;
  283. s->smb_blkdata = i2c_recv(s->smbus);
  284. i2c_nack(s->smbus);
  285. i2c_end_transfer(s->smbus);
  286. } else {
  287. s->smb_blkdata = s->smb_data[s->smb_index];
  288. }
  289. s->smb_index = 0;
  290. s->smb_stat |= STS_INTR;
  291. s->smb_stat &= ~STS_HOST_BUSY;
  292. } else {
  293. if (s->in_i2c_block_read) {
  294. s->smb_blkdata = i2c_recv(s->smbus);
  295. } else {
  296. s->smb_blkdata = s->smb_data[s->smb_index];
  297. }
  298. s->smb_stat |= STS_BYTE_DONE;
  299. }
  300. }
  301. break;
  302. case SMBHSTCNT:
  303. s->smb_ctl = val & ~CTL_START; /* CTL_START always reads 0 */
  304. if (val & CTL_START) {
  305. if (!s->op_done) {
  306. s->smb_index = 0;
  307. s->op_done = true;
  308. if (s->in_i2c_block_read) {
  309. s->in_i2c_block_read = false;
  310. i2c_end_transfer(s->smbus);
  311. }
  312. }
  313. smb_transaction_start(s);
  314. }
  315. if (s->smb_ctl & CTL_KILL) {
  316. s->op_done = true;
  317. s->smb_index = 0;
  318. s->smb_stat |= STS_FAILED;
  319. s->smb_stat &= ~STS_HOST_BUSY;
  320. }
  321. break;
  322. case SMBHSTCMD:
  323. s->smb_cmd = val;
  324. break;
  325. case SMBHSTADD:
  326. s->smb_addr = val;
  327. break;
  328. case SMBHSTDAT0:
  329. s->smb_data0 = val;
  330. break;
  331. case SMBHSTDAT1:
  332. s->smb_data1 = val;
  333. break;
  334. case SMBBLKDAT:
  335. if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
  336. s->smb_index = 0;
  337. }
  338. if (s->smb_auxctl & AUX_BLK) {
  339. s->smb_data[s->smb_index++] = val;
  340. } else {
  341. s->smb_blkdata = val;
  342. }
  343. break;
  344. case SMBAUXCTL:
  345. s->smb_auxctl = val & AUX_MASK;
  346. break;
  347. default:
  348. break;
  349. }
  350. out:
  351. if (s->set_irq) {
  352. s->set_irq(s, smb_irq_value(s));
  353. }
  354. }
  355. static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width)
  356. {
  357. PMSMBus *s = opaque;
  358. uint32_t val;
  359. switch(addr) {
  360. case SMBHSTSTS:
  361. val = s->smb_stat;
  362. if (s->start_transaction_on_status_read) {
  363. /* execute command now */
  364. s->start_transaction_on_status_read = false;
  365. s->smb_stat &= ~STS_HOST_BUSY;
  366. smb_transaction(s);
  367. }
  368. break;
  369. case SMBHSTCNT:
  370. val = s->smb_ctl & CTL_RETURN_MASK;
  371. break;
  372. case SMBHSTCMD:
  373. val = s->smb_cmd;
  374. break;
  375. case SMBHSTADD:
  376. val = s->smb_addr;
  377. break;
  378. case SMBHSTDAT0:
  379. val = s->smb_data0;
  380. break;
  381. case SMBHSTDAT1:
  382. val = s->smb_data1;
  383. break;
  384. case SMBBLKDAT:
  385. if (s->smb_auxctl & AUX_BLK && !s->in_i2c_block_read) {
  386. if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
  387. s->smb_index = 0;
  388. }
  389. val = s->smb_data[s->smb_index++];
  390. if (!s->op_done && s->smb_index == s->smb_data0) {
  391. s->op_done = true;
  392. s->smb_index = 0;
  393. s->smb_stat &= ~STS_HOST_BUSY;
  394. }
  395. } else {
  396. val = s->smb_blkdata;
  397. }
  398. break;
  399. case SMBAUXCTL:
  400. val = s->smb_auxctl;
  401. break;
  402. default:
  403. val = 0;
  404. break;
  405. }
  406. SMBUS_DPRINTF("SMB readb port=0x%04" HWADDR_PRIx " val=0x%02x\n",
  407. addr, val);
  408. if (s->set_irq) {
  409. s->set_irq(s, smb_irq_value(s));
  410. }
  411. return val;
  412. }
  413. static void pm_smbus_reset(PMSMBus *s)
  414. {
  415. s->op_done = true;
  416. s->smb_index = 0;
  417. s->smb_stat = 0;
  418. }
  419. static const MemoryRegionOps pm_smbus_ops = {
  420. .read = smb_ioport_readb,
  421. .write = smb_ioport_writeb,
  422. .valid.min_access_size = 1,
  423. .valid.max_access_size = 1,
  424. .endianness = DEVICE_LITTLE_ENDIAN,
  425. };
  426. bool pm_smbus_vmstate_needed(void)
  427. {
  428. MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
  429. return !mc->smbus_no_migration_support;
  430. }
  431. const VMStateDescription pmsmb_vmstate = {
  432. .name = "pmsmb",
  433. .version_id = 1,
  434. .minimum_version_id = 1,
  435. .fields = (VMStateField[]) {
  436. VMSTATE_UINT8(smb_stat, PMSMBus),
  437. VMSTATE_UINT8(smb_ctl, PMSMBus),
  438. VMSTATE_UINT8(smb_cmd, PMSMBus),
  439. VMSTATE_UINT8(smb_addr, PMSMBus),
  440. VMSTATE_UINT8(smb_data0, PMSMBus),
  441. VMSTATE_UINT8(smb_data1, PMSMBus),
  442. VMSTATE_UINT32(smb_index, PMSMBus),
  443. VMSTATE_UINT8_ARRAY(smb_data, PMSMBus, PM_SMBUS_MAX_MSG_SIZE),
  444. VMSTATE_UINT8(smb_auxctl, PMSMBus),
  445. VMSTATE_UINT8(smb_blkdata, PMSMBus),
  446. VMSTATE_BOOL(i2c_enable, PMSMBus),
  447. VMSTATE_BOOL(op_done, PMSMBus),
  448. VMSTATE_BOOL(in_i2c_block_read, PMSMBus),
  449. VMSTATE_BOOL(start_transaction_on_status_read, PMSMBus),
  450. VMSTATE_END_OF_LIST()
  451. }
  452. };
  453. void pm_smbus_init(DeviceState *parent, PMSMBus *smb, bool force_aux_blk)
  454. {
  455. smb->op_done = true;
  456. smb->reset = pm_smbus_reset;
  457. smb->smbus = i2c_init_bus(parent, "i2c");
  458. if (force_aux_blk) {
  459. smb->smb_auxctl |= AUX_BLK;
  460. }
  461. memory_region_init_io(&smb->io, OBJECT(parent), &pm_smbus_ops, smb,
  462. "pm-smbus", 64);
  463. }