xref: /rk3399_ARM-atf/plat/qti/common/src/spmi_arb.c (revision f40008a4be26dc43cbf50f68c4f20803ea735807)
1*f40008a4SJulius Werner /*
2*f40008a4SJulius Werner  * Copyright (c) 2020, Google LLC. All rights reserved.
3*f40008a4SJulius Werner  *
4*f40008a4SJulius Werner  * SPDX-License-Identifier: BSD-3-Clause
5*f40008a4SJulius Werner  */
6*f40008a4SJulius Werner 
7*f40008a4SJulius Werner #include <common/debug.h>
8*f40008a4SJulius Werner #include <drivers/delay_timer.h>
9*f40008a4SJulius Werner #include <lib/mmio.h>
10*f40008a4SJulius Werner 
11*f40008a4SJulius Werner #include <spmi_arb.h>
12*f40008a4SJulius Werner 
13*f40008a4SJulius Werner #define REG_APID_MAP(apid)	(0x0C440900 + 4 * i)
14*f40008a4SJulius Werner #define NUM_APID		0x80
15*f40008a4SJulius Werner 
16*f40008a4SJulius Werner #define PPID_MASK		(0xfff << 8)
17*f40008a4SJulius Werner 
18*f40008a4SJulius Werner #define REG_ARB_CMD(apid)	(0x0C600000 + 0x10000 * apid)
19*f40008a4SJulius Werner /* These are opcodes specific to this SPMI arbitrator, *not* SPMI commands. */
20*f40008a4SJulius Werner #define OPC_EXT_WRITEL		0
21*f40008a4SJulius Werner #define OPC_EXT_READL		1
22*f40008a4SJulius Werner 
23*f40008a4SJulius Werner #define REG_ARB_STATUS(apid)	(0x0C600008 + 0x10000 * apid)
24*f40008a4SJulius Werner #define ARB_STATUS_DONE		BIT(0)
25*f40008a4SJulius Werner #define ARB_STATUS_FAILURE	BIT(1)
26*f40008a4SJulius Werner #define ARB_STATUS_DENIED	BIT(2)
27*f40008a4SJulius Werner #define ARB_STATUS_DROPPED	BIT(3)
28*f40008a4SJulius Werner 
29*f40008a4SJulius Werner /* Fake status to report driver errors. */
30*f40008a4SJulius Werner #define ARB_FAKE_STATUS_TIMEOUT	BIT(8)
31*f40008a4SJulius Werner 
32*f40008a4SJulius Werner #define REG_ARB_RDATA0(apid)	(0x0C600018 + 0x10000 * apid)
33*f40008a4SJulius Werner #define REG_ARB_WDATA0(apid)	(0x0C600010 + 0x10000 * apid)
34*f40008a4SJulius Werner 
35*f40008a4SJulius Werner static int addr_to_apid(uint32_t addr)
36*f40008a4SJulius Werner {
37*f40008a4SJulius Werner 	unsigned int i;
38*f40008a4SJulius Werner 
39*f40008a4SJulius Werner 	for (i = 0U; i < NUM_APID; i++) {
40*f40008a4SJulius Werner 		uint32_t reg = mmio_read_32(REG_APID_MAP(i));
41*f40008a4SJulius Werner 		if ((reg != 0U) && ((addr & PPID_MASK) == (reg & PPID_MASK))) {
42*f40008a4SJulius Werner 			return i;
43*f40008a4SJulius Werner 		}
44*f40008a4SJulius Werner 	}
45*f40008a4SJulius Werner 
46*f40008a4SJulius Werner 	return -1;
47*f40008a4SJulius Werner }
48*f40008a4SJulius Werner 
49*f40008a4SJulius Werner static int wait_for_done(uint16_t apid)
50*f40008a4SJulius Werner {
51*f40008a4SJulius Werner 	unsigned int timeout = 100;
52*f40008a4SJulius Werner 
53*f40008a4SJulius Werner 	while (timeout-- != 0U) {
54*f40008a4SJulius Werner 		uint32_t status = mmio_read_32(REG_ARB_STATUS(apid));
55*f40008a4SJulius Werner 		if ((status & ARB_STATUS_DONE) != 0U) {
56*f40008a4SJulius Werner 			if ((status & ARB_STATUS_FAILURE) != 0U ||
57*f40008a4SJulius Werner 			    (status & ARB_STATUS_DENIED) != 0U ||
58*f40008a4SJulius Werner 			    (status & ARB_STATUS_DROPPED) != 0U) {
59*f40008a4SJulius Werner 				return status & 0xff;
60*f40008a4SJulius Werner 			}
61*f40008a4SJulius Werner 			return 0;
62*f40008a4SJulius Werner 		}
63*f40008a4SJulius Werner 		mdelay(1);
64*f40008a4SJulius Werner 	}
65*f40008a4SJulius Werner 	ERROR("SPMI_ARB timeout!\n");
66*f40008a4SJulius Werner 	return ARB_FAKE_STATUS_TIMEOUT;
67*f40008a4SJulius Werner }
68*f40008a4SJulius Werner 
69*f40008a4SJulius Werner static void arb_command(uint16_t apid, uint8_t opcode, uint32_t addr,
70*f40008a4SJulius Werner 			uint8_t bytes)
71*f40008a4SJulius Werner {
72*f40008a4SJulius Werner 	mmio_write_32(REG_ARB_CMD(apid), (uint32_t)opcode << 27 |
73*f40008a4SJulius Werner 					 (addr & 0xff) << 4 | (bytes - 1));
74*f40008a4SJulius Werner }
75*f40008a4SJulius Werner 
76*f40008a4SJulius Werner int spmi_arb_read8(uint32_t addr)
77*f40008a4SJulius Werner {
78*f40008a4SJulius Werner 	int apid = addr_to_apid(addr);
79*f40008a4SJulius Werner 
80*f40008a4SJulius Werner 	if (apid < 0) {
81*f40008a4SJulius Werner 		return apid;
82*f40008a4SJulius Werner 	}
83*f40008a4SJulius Werner 
84*f40008a4SJulius Werner 	arb_command(apid, OPC_EXT_READL, addr, 1);
85*f40008a4SJulius Werner 
86*f40008a4SJulius Werner 	int ret = wait_for_done(apid);
87*f40008a4SJulius Werner 	if (ret != 0) {
88*f40008a4SJulius Werner 		ERROR("SPMI_ARB read error [0x%x]: 0x%x\n", addr, ret);
89*f40008a4SJulius Werner 		return ret;
90*f40008a4SJulius Werner 	}
91*f40008a4SJulius Werner 
92*f40008a4SJulius Werner 	return mmio_read_32(REG_ARB_RDATA0(apid)) & 0xff;
93*f40008a4SJulius Werner }
94*f40008a4SJulius Werner 
95*f40008a4SJulius Werner int spmi_arb_write8(uint32_t addr, uint8_t data)
96*f40008a4SJulius Werner {
97*f40008a4SJulius Werner 	int apid = addr_to_apid(addr);
98*f40008a4SJulius Werner 
99*f40008a4SJulius Werner 	if (apid < 0) {
100*f40008a4SJulius Werner 		return apid;
101*f40008a4SJulius Werner 	}
102*f40008a4SJulius Werner 
103*f40008a4SJulius Werner 	mmio_write_32(REG_ARB_WDATA0(apid), data);
104*f40008a4SJulius Werner 	arb_command(apid, OPC_EXT_WRITEL, addr, 1);
105*f40008a4SJulius Werner 
106*f40008a4SJulius Werner 	int ret = wait_for_done(apid);
107*f40008a4SJulius Werner 	if (ret != 0) {
108*f40008a4SJulius Werner 		ERROR("SPMI_ARB write error [0x%x] = 0x%x: 0x%x\n",
109*f40008a4SJulius Werner 		      addr, data, ret);
110*f40008a4SJulius Werner 	}
111*f40008a4SJulius Werner 
112*f40008a4SJulius Werner 	return ret;
113*f40008a4SJulius Werner }
114