iobp.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2016 Google, Inc
  4. *
  5. * Modified from coreboot
  6. */
  7. #include <common.h>
  8. #include <errno.h>
  9. #include <asm/intel_regs.h>
  10. #include <asm/io.h>
  11. #include <asm/arch/pch.h>
  12. #define IOBP_RETRY 1000
  13. /* IO Buffer Programming */
  14. #define IOBPIRI 0x2330
  15. #define IOBPD 0x2334
  16. #define IOBPS 0x2338
  17. #define IOBPS_READY 0x0001
  18. #define IOBPS_TX_MASK 0x0006
  19. #define IOBPS_MASK 0xff00
  20. #define IOBPS_READ 0x0600
  21. #define IOBPS_WRITE 0x0700
  22. #define IOBPU 0x233a
  23. #define IOBPU_MAGIC 0xf000
  24. #define IOBP_PCICFG_READ 0x0400
  25. #define IOBP_PCICFG_WRITE 0x0500
  26. static inline int iobp_poll(void)
  27. {
  28. unsigned try;
  29. for (try = IOBP_RETRY; try > 0; try--) {
  30. u16 status = readw(RCB_REG(IOBPS));
  31. if ((status & IOBPS_READY) == 0)
  32. return 1;
  33. udelay(10);
  34. }
  35. printf("IOBP: timeout waiting for transaction to complete\n");
  36. return 0;
  37. }
  38. int pch_iobp_trans_start(u32 address, int op)
  39. {
  40. if (!iobp_poll())
  41. return 0;
  42. /* Set the address */
  43. writel(address, RCB_REG(IOBPIRI));
  44. /* READ OPCODE */
  45. clrsetbits_le16(RCB_REG(IOBPS), IOBPS_MASK, op);
  46. return 1;
  47. }
  48. int pch_iobp_trans_finish(void)
  49. {
  50. u16 status;
  51. /* Undocumented magic */
  52. writew(IOBPU_MAGIC, RCB_REG(IOBPU));
  53. /* Set ready bit */
  54. setbits_le16(RCB_REG(IOBPS), IOBPS_READY);
  55. if (!iobp_poll())
  56. return 1;
  57. /* Check for successful transaction */
  58. status = readw(RCB_REG(IOBPS));
  59. if (status & IOBPS_TX_MASK)
  60. return 1;
  61. return 0;
  62. }
  63. u32 pch_iobp_read(u32 address)
  64. {
  65. if (!pch_iobp_trans_start(address, IOBPS_READ))
  66. return 0;
  67. if (pch_iobp_trans_finish()) {
  68. printf("IOBP: read 0x%08x failed\n", address);
  69. return 0;
  70. }
  71. /* Read IOBP data */
  72. return readl(RCB_REG(IOBPD));
  73. }
  74. int pch_iobp_write(u32 address, u32 data)
  75. {
  76. if (!pch_iobp_trans_start(address, IOBPS_WRITE))
  77. return -EIO;
  78. writel(data, RCB_REG(IOBPD));
  79. if (pch_iobp_trans_finish()) {
  80. printf("IOBP: write 0x%08x failed\n", address);
  81. return -EIO;
  82. }
  83. return 0;
  84. }
  85. int pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
  86. {
  87. u32 data = pch_iobp_read(address);
  88. /* Update the data */
  89. data &= andvalue;
  90. data |= orvalue;
  91. return pch_iobp_write(address, data);
  92. }
  93. int pch_iobp_exec(u32 addr, u16 op_code, u8 route_id, u32 *data, u8 *resp)
  94. {
  95. if (!data || !resp)
  96. return 0;
  97. *resp = -1;
  98. if (!iobp_poll())
  99. return -EIO;
  100. writel(addr, RCB_REG(IOBPIRI));
  101. clrsetbits_le16(RCB_REG(IOBPS), 0xff00, op_code);
  102. writew(IOBPU_MAGIC | route_id, RCB_REG(IOBPU));
  103. writel(*data, RCB_REG(IOBPD));
  104. /* Set IOBPS[0] to trigger IOBP transaction*/
  105. setbits_le16(RCB_REG(IOBPS), 1);
  106. if (!iobp_poll())
  107. return -EIO;
  108. *resp = (readw(RCB_REG(IOBPS)) & IOBPS_TX_MASK) >> 1;
  109. *data = readl(RCB_REG(IOBPD));
  110. return 0;
  111. }