1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
21e6f4e58SSimon Glass /*
31e6f4e58SSimon Glass * Copyright (c) 2016 Google, Inc
41e6f4e58SSimon Glass *
51e6f4e58SSimon Glass * Modified from coreboot
61e6f4e58SSimon Glass */
71e6f4e58SSimon Glass
81e6f4e58SSimon Glass #include <common.h>
91e6f4e58SSimon Glass #include <errno.h>
101e6f4e58SSimon Glass #include <asm/intel_regs.h>
111e6f4e58SSimon Glass #include <asm/io.h>
121e6f4e58SSimon Glass #include <asm/arch/pch.h>
131e6f4e58SSimon Glass
141e6f4e58SSimon Glass #define IOBP_RETRY 1000
151e6f4e58SSimon Glass
161e6f4e58SSimon Glass /* IO Buffer Programming */
171e6f4e58SSimon Glass #define IOBPIRI 0x2330
181e6f4e58SSimon Glass #define IOBPD 0x2334
191e6f4e58SSimon Glass #define IOBPS 0x2338
201e6f4e58SSimon Glass #define IOBPS_READY 0x0001
211e6f4e58SSimon Glass #define IOBPS_TX_MASK 0x0006
221e6f4e58SSimon Glass #define IOBPS_MASK 0xff00
231e6f4e58SSimon Glass #define IOBPS_READ 0x0600
241e6f4e58SSimon Glass #define IOBPS_WRITE 0x0700
251e6f4e58SSimon Glass #define IOBPU 0x233a
261e6f4e58SSimon Glass #define IOBPU_MAGIC 0xf000
271e6f4e58SSimon Glass #define IOBP_PCICFG_READ 0x0400
281e6f4e58SSimon Glass #define IOBP_PCICFG_WRITE 0x0500
291e6f4e58SSimon Glass
iobp_poll(void)301e6f4e58SSimon Glass static inline int iobp_poll(void)
311e6f4e58SSimon Glass {
321e6f4e58SSimon Glass unsigned try;
331e6f4e58SSimon Glass
341e6f4e58SSimon Glass for (try = IOBP_RETRY; try > 0; try--) {
351e6f4e58SSimon Glass u16 status = readw(RCB_REG(IOBPS));
361e6f4e58SSimon Glass if ((status & IOBPS_READY) == 0)
371e6f4e58SSimon Glass return 1;
381e6f4e58SSimon Glass udelay(10);
391e6f4e58SSimon Glass }
401e6f4e58SSimon Glass
411e6f4e58SSimon Glass printf("IOBP: timeout waiting for transaction to complete\n");
421e6f4e58SSimon Glass return 0;
431e6f4e58SSimon Glass }
441e6f4e58SSimon Glass
pch_iobp_trans_start(u32 address,int op)451e6f4e58SSimon Glass int pch_iobp_trans_start(u32 address, int op)
461e6f4e58SSimon Glass {
471e6f4e58SSimon Glass if (!iobp_poll())
481e6f4e58SSimon Glass return 0;
491e6f4e58SSimon Glass
501e6f4e58SSimon Glass /* Set the address */
511e6f4e58SSimon Glass writel(address, RCB_REG(IOBPIRI));
521e6f4e58SSimon Glass
531e6f4e58SSimon Glass /* READ OPCODE */
541e6f4e58SSimon Glass clrsetbits_le16(RCB_REG(IOBPS), IOBPS_MASK, op);
551e6f4e58SSimon Glass
561e6f4e58SSimon Glass return 1;
571e6f4e58SSimon Glass }
581e6f4e58SSimon Glass
pch_iobp_trans_finish(void)591e6f4e58SSimon Glass int pch_iobp_trans_finish(void)
601e6f4e58SSimon Glass {
611e6f4e58SSimon Glass u16 status;
621e6f4e58SSimon Glass
631e6f4e58SSimon Glass /* Undocumented magic */
641e6f4e58SSimon Glass writew(IOBPU_MAGIC, RCB_REG(IOBPU));
651e6f4e58SSimon Glass
661e6f4e58SSimon Glass /* Set ready bit */
671e6f4e58SSimon Glass setbits_le16(RCB_REG(IOBPS), IOBPS_READY);
681e6f4e58SSimon Glass
691e6f4e58SSimon Glass if (!iobp_poll())
701e6f4e58SSimon Glass return 1;
711e6f4e58SSimon Glass
721e6f4e58SSimon Glass /* Check for successful transaction */
731e6f4e58SSimon Glass status = readw(RCB_REG(IOBPS));
741e6f4e58SSimon Glass if (status & IOBPS_TX_MASK)
751e6f4e58SSimon Glass return 1;
761e6f4e58SSimon Glass
771e6f4e58SSimon Glass return 0;
781e6f4e58SSimon Glass }
791e6f4e58SSimon Glass
pch_iobp_read(u32 address)801e6f4e58SSimon Glass u32 pch_iobp_read(u32 address)
811e6f4e58SSimon Glass {
821e6f4e58SSimon Glass if (!pch_iobp_trans_start(address, IOBPS_READ))
831e6f4e58SSimon Glass return 0;
841e6f4e58SSimon Glass if (pch_iobp_trans_finish()) {
851e6f4e58SSimon Glass printf("IOBP: read 0x%08x failed\n", address);
861e6f4e58SSimon Glass return 0;
871e6f4e58SSimon Glass }
881e6f4e58SSimon Glass
891e6f4e58SSimon Glass /* Read IOBP data */
901e6f4e58SSimon Glass return readl(RCB_REG(IOBPD));
911e6f4e58SSimon Glass }
921e6f4e58SSimon Glass
pch_iobp_write(u32 address,u32 data)931e6f4e58SSimon Glass int pch_iobp_write(u32 address, u32 data)
941e6f4e58SSimon Glass {
951e6f4e58SSimon Glass if (!pch_iobp_trans_start(address, IOBPS_WRITE))
961e6f4e58SSimon Glass return -EIO;
971e6f4e58SSimon Glass
981e6f4e58SSimon Glass writel(data, RCB_REG(IOBPD));
991e6f4e58SSimon Glass
1001e6f4e58SSimon Glass if (pch_iobp_trans_finish()) {
1011e6f4e58SSimon Glass printf("IOBP: write 0x%08x failed\n", address);
1021e6f4e58SSimon Glass return -EIO;
1031e6f4e58SSimon Glass }
1041e6f4e58SSimon Glass
1051e6f4e58SSimon Glass return 0;
1061e6f4e58SSimon Glass }
1071e6f4e58SSimon Glass
pch_iobp_update(u32 address,u32 andvalue,u32 orvalue)1081e6f4e58SSimon Glass int pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
1091e6f4e58SSimon Glass {
1101e6f4e58SSimon Glass u32 data = pch_iobp_read(address);
1111e6f4e58SSimon Glass
1121e6f4e58SSimon Glass /* Update the data */
1131e6f4e58SSimon Glass data &= andvalue;
1141e6f4e58SSimon Glass data |= orvalue;
1151e6f4e58SSimon Glass
1161e6f4e58SSimon Glass return pch_iobp_write(address, data);
1171e6f4e58SSimon Glass }
1181e6f4e58SSimon Glass
pch_iobp_exec(u32 addr,u16 op_code,u8 route_id,u32 * data,u8 * resp)1191e6f4e58SSimon Glass int pch_iobp_exec(u32 addr, u16 op_code, u8 route_id, u32 *data, u8 *resp)
1201e6f4e58SSimon Glass {
1211e6f4e58SSimon Glass if (!data || !resp)
1221e6f4e58SSimon Glass return 0;
1231e6f4e58SSimon Glass
1241e6f4e58SSimon Glass *resp = -1;
1251e6f4e58SSimon Glass if (!iobp_poll())
1261e6f4e58SSimon Glass return -EIO;
1271e6f4e58SSimon Glass
1281e6f4e58SSimon Glass writel(addr, RCB_REG(IOBPIRI));
1291e6f4e58SSimon Glass clrsetbits_le16(RCB_REG(IOBPS), 0xff00, op_code);
1301e6f4e58SSimon Glass writew(IOBPU_MAGIC | route_id, RCB_REG(IOBPU));
1311e6f4e58SSimon Glass
1321e6f4e58SSimon Glass writel(*data, RCB_REG(IOBPD));
1331e6f4e58SSimon Glass /* Set IOBPS[0] to trigger IOBP transaction*/
1341e6f4e58SSimon Glass setbits_le16(RCB_REG(IOBPS), 1);
1351e6f4e58SSimon Glass
1361e6f4e58SSimon Glass if (!iobp_poll())
1371e6f4e58SSimon Glass return -EIO;
1381e6f4e58SSimon Glass
1391e6f4e58SSimon Glass *resp = (readw(RCB_REG(IOBPS)) & IOBPS_TX_MASK) >> 1;
1401e6f4e58SSimon Glass *data = readl(RCB_REG(IOBPD));
1411e6f4e58SSimon Glass
1421e6f4e58SSimon Glass return 0;
1431e6f4e58SSimon Glass }
144