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