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