iobp.c 2.6 KB

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