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