xref: /openbmc/u-boot/arch/x86/cpu/broadwell/iobp.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
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