xref: /rk3399_ARM-atf/drivers/renesas/common/iic_dvfs/iic_dvfs.c (revision be92e5a22f83fe5e580b4c60148ec9b150b82c23)
1*be92e5a2SBiju Das /*
2*be92e5a2SBiju Das  * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
3*be92e5a2SBiju Das  *
4*be92e5a2SBiju Das  * SPDX-License-Identifier: BSD-3-Clause
5*be92e5a2SBiju Das  */
6*be92e5a2SBiju Das 
7*be92e5a2SBiju Das #include <common/debug.h>
8*be92e5a2SBiju Das #include <lib/mmio.h>
9*be92e5a2SBiju Das 
10*be92e5a2SBiju Das #include "cpg_registers.h"
11*be92e5a2SBiju Das #include "iic_dvfs.h"
12*be92e5a2SBiju Das #include "rcar_def.h"
13*be92e5a2SBiju Das #include "rcar_private.h"
14*be92e5a2SBiju Das 
15*be92e5a2SBiju Das #define DVFS_RETRY_MAX				(2U)
16*be92e5a2SBiju Das 
17*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCL_EXTAL_TYPE_0		(0x07U)
18*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCL_EXTAL_TYPE_1		(0x09U)
19*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCL_EXTAL_TYPE_2		(0x0BU)
20*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCL_EXTAL_TYPE_3		(0x0EU)
21*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCL_EXTAL_TYPE_E		(0x15U)
22*be92e5a2SBiju Das 
23*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCH_EXTAL_TYPE_0		(0x01U)
24*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCH_EXTAL_TYPE_1		(0x02U)
25*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCH_EXTAL_TYPE_2		(0x03U)
26*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCH_EXTAL_TYPE_3		(0x05U)
27*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCH_EXTAL_TYPE_E		(0x07U)
28*be92e5a2SBiju Das 
29*be92e5a2SBiju Das #define CPG_BIT_SMSTPCR9_DVFS			(0x04000000U)
30*be92e5a2SBiju Das 
31*be92e5a2SBiju Das #define IIC_DVFS_REG_BASE			(0xE60B0000U)
32*be92e5a2SBiju Das #define IIC_DVFS_REG_ICDR			(IIC_DVFS_REG_BASE + 0x0000U)
33*be92e5a2SBiju Das #define IIC_DVFS_REG_ICCR			(IIC_DVFS_REG_BASE + 0x0004U)
34*be92e5a2SBiju Das #define IIC_DVFS_REG_ICSR			(IIC_DVFS_REG_BASE + 0x0008U)
35*be92e5a2SBiju Das #define IIC_DVFS_REG_ICIC			(IIC_DVFS_REG_BASE + 0x000CU)
36*be92e5a2SBiju Das #define IIC_DVFS_REG_ICCL			(IIC_DVFS_REG_BASE + 0x0010U)
37*be92e5a2SBiju Das #define IIC_DVFS_REG_ICCH			(IIC_DVFS_REG_BASE + 0x0014U)
38*be92e5a2SBiju Das 
39*be92e5a2SBiju Das #define IIC_DVFS_BIT_ICSR_BUSY			(0x10U)
40*be92e5a2SBiju Das #define IIC_DVFS_BIT_ICSR_AL			(0x08U)
41*be92e5a2SBiju Das #define IIC_DVFS_BIT_ICSR_TACK			(0x04U)
42*be92e5a2SBiju Das #define IIC_DVFS_BIT_ICSR_WAIT			(0x02U)
43*be92e5a2SBiju Das #define IIC_DVFS_BIT_ICSR_DTE			(0x01U)
44*be92e5a2SBiju Das 
45*be92e5a2SBiju Das #define IIC_DVFS_BIT_ICCR_ENABLE		(0x80U)
46*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCR_START			(0x94U)
47*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCR_STOP			(0x90U)
48*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCR_RETRANSMISSION	(0x94U)
49*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCR_CHANGE		(0x81U)
50*be92e5a2SBiju Das #define IIC_DVFS_SET_ICCR_STOP_READ		(0xC0U)
51*be92e5a2SBiju Das 
52*be92e5a2SBiju Das #define IIC_DVFS_BIT_ICIC_TACKE			(0x04U)
53*be92e5a2SBiju Das #define IIC_DVFS_BIT_ICIC_WAITE			(0x02U)
54*be92e5a2SBiju Das #define IIC_DVFS_BIT_ICIC_DTEE			(0x01U)
55*be92e5a2SBiju Das 
56*be92e5a2SBiju Das #define DVFS_READ_MODE				(0x01U)
57*be92e5a2SBiju Das #define DVFS_WRITE_MODE				(0x00U)
58*be92e5a2SBiju Das 
59*be92e5a2SBiju Das #define IIC_DVFS_SET_DUMMY			(0x52U)
60*be92e5a2SBiju Das #define IIC_DVFS_SET_BUSY_LOOP			(500000000U)
61*be92e5a2SBiju Das 
62*be92e5a2SBiju Das enum dvfs_state_t {
63*be92e5a2SBiju Das 	DVFS_START = 0,
64*be92e5a2SBiju Das 	DVFS_STOP,
65*be92e5a2SBiju Das 	DVFS_RETRANSMIT,
66*be92e5a2SBiju Das 	DVFS_READ,
67*be92e5a2SBiju Das 	DVFS_STOP_READ,
68*be92e5a2SBiju Das 	DVFS_SET_SLAVE_READ,
69*be92e5a2SBiju Das 	DVFS_SET_SLAVE,
70*be92e5a2SBiju Das 	DVFS_WRITE_ADDR,
71*be92e5a2SBiju Das 	DVFS_WRITE_DATA,
72*be92e5a2SBiju Das 	DVFS_CHANGE_SEND_TO_RECEIVE,
73*be92e5a2SBiju Das 	DVFS_DONE,
74*be92e5a2SBiju Das };
75*be92e5a2SBiju Das 
76*be92e5a2SBiju Das #define DVFS_PROCESS			(1)
77*be92e5a2SBiju Das #define DVFS_COMPLETE			(0)
78*be92e5a2SBiju Das #define DVFS_ERROR			(-1)
79*be92e5a2SBiju Das 
80*be92e5a2SBiju Das #if IMAGE_BL31
81*be92e5a2SBiju Das #define IIC_DVFS_FUNC(__name, ...)					\
82*be92e5a2SBiju Das static int32_t	__attribute__ ((section(".system_ram")))		\
83*be92e5a2SBiju Das dvfs_ ##__name(__VA_ARGS__)
84*be92e5a2SBiju Das 
85*be92e5a2SBiju Das #define RCAR_DVFS_API(__name, ...)					\
86*be92e5a2SBiju Das int32_t __attribute__ ((section(".system_ram")))			\
87*be92e5a2SBiju Das rcar_iic_dvfs_ ##__name(__VA_ARGS__)
88*be92e5a2SBiju Das 
89*be92e5a2SBiju Das #else
90*be92e5a2SBiju Das #define IIC_DVFS_FUNC(__name, ...)					\
91*be92e5a2SBiju Das static int32_t dvfs_ ##__name(__VA_ARGS__)
92*be92e5a2SBiju Das 
93*be92e5a2SBiju Das #define RCAR_DVFS_API(__name, ...)					\
94*be92e5a2SBiju Das int32_t rcar_iic_dvfs_ ##__name(__VA_ARGS__)
95*be92e5a2SBiju Das #endif
96*be92e5a2SBiju Das 
97*be92e5a2SBiju Das IIC_DVFS_FUNC(check_error, enum dvfs_state_t *state, uint32_t *err, uint8_t mode)
98*be92e5a2SBiju Das {
99*be92e5a2SBiju Das 	uint8_t icsr_al = 0U, icsr_tack = 0U;
100*be92e5a2SBiju Das 	uint8_t reg, stop;
101*be92e5a2SBiju Das 	uint32_t i = 0U;
102*be92e5a2SBiju Das 
103*be92e5a2SBiju Das 	stop = mode == DVFS_READ_MODE ? IIC_DVFS_SET_ICCR_STOP_READ :
104*be92e5a2SBiju Das 	    IIC_DVFS_SET_ICCR_STOP;
105*be92e5a2SBiju Das 
106*be92e5a2SBiju Das 	reg = mmio_read_8(IIC_DVFS_REG_ICSR);
107*be92e5a2SBiju Das 	icsr_al = (reg & IIC_DVFS_BIT_ICSR_AL) == IIC_DVFS_BIT_ICSR_AL;
108*be92e5a2SBiju Das 	icsr_tack = (reg & IIC_DVFS_BIT_ICSR_TACK) == IIC_DVFS_BIT_ICSR_TACK;
109*be92e5a2SBiju Das 
110*be92e5a2SBiju Das 	if (icsr_al == 0U && icsr_tack == 0U) {
111*be92e5a2SBiju Das 		return DVFS_PROCESS;
112*be92e5a2SBiju Das 	}
113*be92e5a2SBiju Das 
114*be92e5a2SBiju Das 	if (icsr_al) {
115*be92e5a2SBiju Das 		reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_AL;
116*be92e5a2SBiju Das 		mmio_write_8(IIC_DVFS_REG_ICSR, reg);
117*be92e5a2SBiju Das 
118*be92e5a2SBiju Das 		if (*state == DVFS_SET_SLAVE) {
119*be92e5a2SBiju Das 			mmio_write_8(IIC_DVFS_REG_ICDR, IIC_DVFS_SET_DUMMY);
120*be92e5a2SBiju Das 		}
121*be92e5a2SBiju Das 
122*be92e5a2SBiju Das 		do {
123*be92e5a2SBiju Das 			reg = mmio_read_8(IIC_DVFS_REG_ICSR) &
124*be92e5a2SBiju Das 			    IIC_DVFS_BIT_ICSR_WAIT;
125*be92e5a2SBiju Das 		} while (reg == 0U);
126*be92e5a2SBiju Das 
127*be92e5a2SBiju Das 		mmio_write_8(IIC_DVFS_REG_ICCR, stop);
128*be92e5a2SBiju Das 
129*be92e5a2SBiju Das 		reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT;
130*be92e5a2SBiju Das 		mmio_write_8(IIC_DVFS_REG_ICSR, reg);
131*be92e5a2SBiju Das 
132*be92e5a2SBiju Das 		i = 0U;
133*be92e5a2SBiju Das 		do {
134*be92e5a2SBiju Das 			reg = mmio_read_8(IIC_DVFS_REG_ICSR) &
135*be92e5a2SBiju Das 			    IIC_DVFS_BIT_ICSR_BUSY;
136*be92e5a2SBiju Das 			if (reg == 0U) {
137*be92e5a2SBiju Das 				break;
138*be92e5a2SBiju Das 			}
139*be92e5a2SBiju Das 
140*be92e5a2SBiju Das 			if (i++ > IIC_DVFS_SET_BUSY_LOOP) {
141*be92e5a2SBiju Das 				panic();
142*be92e5a2SBiju Das 			}
143*be92e5a2SBiju Das 
144*be92e5a2SBiju Das 		} while (true);
145*be92e5a2SBiju Das 
146*be92e5a2SBiju Das 		mmio_write_8(IIC_DVFS_REG_ICCR, 0x00U);
147*be92e5a2SBiju Das 
148*be92e5a2SBiju Das 		(*err)++;
149*be92e5a2SBiju Das 		if (*err > DVFS_RETRY_MAX) {
150*be92e5a2SBiju Das 			return DVFS_ERROR;
151*be92e5a2SBiju Das 		}
152*be92e5a2SBiju Das 
153*be92e5a2SBiju Das 		*state = DVFS_START;
154*be92e5a2SBiju Das 
155*be92e5a2SBiju Das 		return DVFS_PROCESS;
156*be92e5a2SBiju Das 
157*be92e5a2SBiju Das 	}
158*be92e5a2SBiju Das 
159*be92e5a2SBiju Das 	/* icsr_tack */
160*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCR, stop);
161*be92e5a2SBiju Das 
162*be92e5a2SBiju Das 	reg = mmio_read_8(IIC_DVFS_REG_ICIC);
163*be92e5a2SBiju Das 	reg &= ~(IIC_DVFS_BIT_ICIC_WAITE | IIC_DVFS_BIT_ICIC_DTEE);
164*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICIC, reg);
165*be92e5a2SBiju Das 
166*be92e5a2SBiju Das 	reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_TACK;
167*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICSR, reg);
168*be92e5a2SBiju Das 
169*be92e5a2SBiju Das 	i = 0U;
170*be92e5a2SBiju Das 	while ((mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_BUSY) != 0U) {
171*be92e5a2SBiju Das 		if (i++ > IIC_DVFS_SET_BUSY_LOOP) {
172*be92e5a2SBiju Das 			panic();
173*be92e5a2SBiju Das 		}
174*be92e5a2SBiju Das 	}
175*be92e5a2SBiju Das 
176*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCR, 0U);
177*be92e5a2SBiju Das 	(*err)++;
178*be92e5a2SBiju Das 
179*be92e5a2SBiju Das 	if (*err > DVFS_RETRY_MAX) {
180*be92e5a2SBiju Das 		return DVFS_ERROR;
181*be92e5a2SBiju Das 	}
182*be92e5a2SBiju Das 
183*be92e5a2SBiju Das 	*state = DVFS_START;
184*be92e5a2SBiju Das 
185*be92e5a2SBiju Das 	return DVFS_PROCESS;
186*be92e5a2SBiju Das }
187*be92e5a2SBiju Das 
188*be92e5a2SBiju Das IIC_DVFS_FUNC(start, enum dvfs_state_t *state)
189*be92e5a2SBiju Das {
190*be92e5a2SBiju Das 	uint8_t iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_E;
191*be92e5a2SBiju Das 	uint8_t icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_E;
192*be92e5a2SBiju Das 	int32_t result = DVFS_PROCESS;
193*be92e5a2SBiju Das 	uint32_t reg, lsi_product;
194*be92e5a2SBiju Das 	uint8_t mode;
195*be92e5a2SBiju Das 
196*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICCR) | IIC_DVFS_BIT_ICCR_ENABLE;
197*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCR, mode);
198*be92e5a2SBiju Das 
199*be92e5a2SBiju Das 	lsi_product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK;
200*be92e5a2SBiju Das 	if (lsi_product == PRR_PRODUCT_E3) {
201*be92e5a2SBiju Das 		goto start;
202*be92e5a2SBiju Das 	}
203*be92e5a2SBiju Das 
204*be92e5a2SBiju Das 	reg = mmio_read_32(RCAR_MODEMR) & CHECK_MD13_MD14;
205*be92e5a2SBiju Das 	switch (reg) {
206*be92e5a2SBiju Das 	case MD14_MD13_TYPE_0:
207*be92e5a2SBiju Das 		iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_0;
208*be92e5a2SBiju Das 		icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_0;
209*be92e5a2SBiju Das 		break;
210*be92e5a2SBiju Das 	case MD14_MD13_TYPE_1:
211*be92e5a2SBiju Das 		iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_1;
212*be92e5a2SBiju Das 		icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_1;
213*be92e5a2SBiju Das 		break;
214*be92e5a2SBiju Das 	case MD14_MD13_TYPE_2:
215*be92e5a2SBiju Das 		iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_2;
216*be92e5a2SBiju Das 		icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_2;
217*be92e5a2SBiju Das 		break;
218*be92e5a2SBiju Das 	default:
219*be92e5a2SBiju Das 		iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_3;
220*be92e5a2SBiju Das 		icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_3;
221*be92e5a2SBiju Das 		break;
222*be92e5a2SBiju Das 	}
223*be92e5a2SBiju Das start:
224*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCL, iccl);
225*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCH, icch);
226*be92e5a2SBiju Das 
227*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICIC)
228*be92e5a2SBiju Das 	    | IIC_DVFS_BIT_ICIC_TACKE
229*be92e5a2SBiju Das 	    | IIC_DVFS_BIT_ICIC_WAITE | IIC_DVFS_BIT_ICIC_DTEE;
230*be92e5a2SBiju Das 
231*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICIC, mode);
232*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_START);
233*be92e5a2SBiju Das 
234*be92e5a2SBiju Das 	*state = DVFS_SET_SLAVE;
235*be92e5a2SBiju Das 
236*be92e5a2SBiju Das 	return result;
237*be92e5a2SBiju Das }
238*be92e5a2SBiju Das 
239*be92e5a2SBiju Das IIC_DVFS_FUNC(set_slave, enum dvfs_state_t *state, uint32_t *err, uint8_t slave)
240*be92e5a2SBiju Das {
241*be92e5a2SBiju Das 	uint8_t mode;
242*be92e5a2SBiju Das 	int32_t result;
243*be92e5a2SBiju Das 	uint8_t address;
244*be92e5a2SBiju Das 
245*be92e5a2SBiju Das 	result = dvfs_check_error(state, err, DVFS_WRITE_MODE);
246*be92e5a2SBiju Das 	if (result == DVFS_ERROR) {
247*be92e5a2SBiju Das 		return result;
248*be92e5a2SBiju Das 	}
249*be92e5a2SBiju Das 
250*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE;
251*be92e5a2SBiju Das 	if (mode != IIC_DVFS_BIT_ICSR_DTE) {
252*be92e5a2SBiju Das 		return result;
253*be92e5a2SBiju Das 	}
254*be92e5a2SBiju Das 
255*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE;
256*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICIC, mode);
257*be92e5a2SBiju Das 
258*be92e5a2SBiju Das 	address = slave << 1;
259*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICDR, address);
260*be92e5a2SBiju Das 
261*be92e5a2SBiju Das 	*state = DVFS_WRITE_ADDR;
262*be92e5a2SBiju Das 
263*be92e5a2SBiju Das 	return result;
264*be92e5a2SBiju Das }
265*be92e5a2SBiju Das 
266*be92e5a2SBiju Das IIC_DVFS_FUNC(write_addr, enum dvfs_state_t *state, uint32_t *err, uint8_t reg_addr)
267*be92e5a2SBiju Das {
268*be92e5a2SBiju Das 	uint8_t mode;
269*be92e5a2SBiju Das 	int32_t result;
270*be92e5a2SBiju Das 
271*be92e5a2SBiju Das 	result = dvfs_check_error(state, err, DVFS_WRITE_MODE);
272*be92e5a2SBiju Das 	if (result == DVFS_ERROR) {
273*be92e5a2SBiju Das 		return result;
274*be92e5a2SBiju Das 	}
275*be92e5a2SBiju Das 
276*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT;
277*be92e5a2SBiju Das 	if (mode != IIC_DVFS_BIT_ICSR_WAIT) {
278*be92e5a2SBiju Das 		return result;
279*be92e5a2SBiju Das 	}
280*be92e5a2SBiju Das 
281*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICDR, reg_addr);
282*be92e5a2SBiju Das 
283*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT;
284*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICSR, mode);
285*be92e5a2SBiju Das 
286*be92e5a2SBiju Das 	*state = DVFS_WRITE_DATA;
287*be92e5a2SBiju Das 
288*be92e5a2SBiju Das 	return result;
289*be92e5a2SBiju Das }
290*be92e5a2SBiju Das 
291*be92e5a2SBiju Das IIC_DVFS_FUNC(write_data, enum dvfs_state_t *state, uint32_t *err,
292*be92e5a2SBiju Das 	      uint8_t reg_data)
293*be92e5a2SBiju Das {
294*be92e5a2SBiju Das 	int32_t result;
295*be92e5a2SBiju Das 	uint8_t mode;
296*be92e5a2SBiju Das 
297*be92e5a2SBiju Das 	result = dvfs_check_error(state, err, DVFS_WRITE_MODE);
298*be92e5a2SBiju Das 	if (result == DVFS_ERROR) {
299*be92e5a2SBiju Das 		return result;
300*be92e5a2SBiju Das 	}
301*be92e5a2SBiju Das 
302*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT;
303*be92e5a2SBiju Das 	if (mode != IIC_DVFS_BIT_ICSR_WAIT) {
304*be92e5a2SBiju Das 		return result;
305*be92e5a2SBiju Das 	}
306*be92e5a2SBiju Das 
307*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICDR, reg_data);
308*be92e5a2SBiju Das 
309*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT;
310*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICSR, mode);
311*be92e5a2SBiju Das 
312*be92e5a2SBiju Das 	*state = DVFS_STOP;
313*be92e5a2SBiju Das 
314*be92e5a2SBiju Das 	return result;
315*be92e5a2SBiju Das }
316*be92e5a2SBiju Das 
317*be92e5a2SBiju Das IIC_DVFS_FUNC(stop, enum dvfs_state_t *state, uint32_t *err)
318*be92e5a2SBiju Das {
319*be92e5a2SBiju Das 	int32_t result;
320*be92e5a2SBiju Das 	uint8_t mode;
321*be92e5a2SBiju Das 
322*be92e5a2SBiju Das 	result = dvfs_check_error(state, err, DVFS_WRITE_MODE);
323*be92e5a2SBiju Das 	if (result == DVFS_ERROR) {
324*be92e5a2SBiju Das 		return result;
325*be92e5a2SBiju Das 	}
326*be92e5a2SBiju Das 
327*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT;
328*be92e5a2SBiju Das 	if (mode != IIC_DVFS_BIT_ICSR_WAIT) {
329*be92e5a2SBiju Das 		return result;
330*be92e5a2SBiju Das 	}
331*be92e5a2SBiju Das 
332*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_STOP);
333*be92e5a2SBiju Das 
334*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT;
335*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICSR, mode);
336*be92e5a2SBiju Das 
337*be92e5a2SBiju Das 	*state = DVFS_DONE;
338*be92e5a2SBiju Das 
339*be92e5a2SBiju Das 	return result;
340*be92e5a2SBiju Das }
341*be92e5a2SBiju Das 
342*be92e5a2SBiju Das IIC_DVFS_FUNC(done, void)
343*be92e5a2SBiju Das {
344*be92e5a2SBiju Das 	uint32_t i;
345*be92e5a2SBiju Das 
346*be92e5a2SBiju Das 	for (i = 0U; i < IIC_DVFS_SET_BUSY_LOOP; i++) {
347*be92e5a2SBiju Das 		if ((mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_BUSY) != 0U) {
348*be92e5a2SBiju Das 			continue;
349*be92e5a2SBiju Das 		}
350*be92e5a2SBiju Das 		goto done;
351*be92e5a2SBiju Das 	}
352*be92e5a2SBiju Das 
353*be92e5a2SBiju Das 	panic();
354*be92e5a2SBiju Das done:
355*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCR, 0U);
356*be92e5a2SBiju Das 
357*be92e5a2SBiju Das 	return DVFS_COMPLETE;
358*be92e5a2SBiju Das }
359*be92e5a2SBiju Das 
360*be92e5a2SBiju Das IIC_DVFS_FUNC(write_reg_addr_read, enum dvfs_state_t *state, uint32_t *err,
361*be92e5a2SBiju Das 	      uint8_t reg_addr)
362*be92e5a2SBiju Das {
363*be92e5a2SBiju Das 	int32_t result;
364*be92e5a2SBiju Das 	uint8_t mode;
365*be92e5a2SBiju Das 
366*be92e5a2SBiju Das 	result = dvfs_check_error(state, err, DVFS_WRITE_MODE);
367*be92e5a2SBiju Das 	if (result == DVFS_ERROR) {
368*be92e5a2SBiju Das 		return result;
369*be92e5a2SBiju Das 	}
370*be92e5a2SBiju Das 
371*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT;
372*be92e5a2SBiju Das 	if (mode != IIC_DVFS_BIT_ICSR_WAIT) {
373*be92e5a2SBiju Das 		return result;
374*be92e5a2SBiju Das 	}
375*be92e5a2SBiju Das 
376*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICDR, reg_addr);
377*be92e5a2SBiju Das 
378*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT;
379*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICSR, mode);
380*be92e5a2SBiju Das 
381*be92e5a2SBiju Das 	*state = DVFS_RETRANSMIT;
382*be92e5a2SBiju Das 
383*be92e5a2SBiju Das 	return result;
384*be92e5a2SBiju Das }
385*be92e5a2SBiju Das 
386*be92e5a2SBiju Das IIC_DVFS_FUNC(retransmit, enum dvfs_state_t *state, uint32_t *err)
387*be92e5a2SBiju Das {
388*be92e5a2SBiju Das 	int32_t result;
389*be92e5a2SBiju Das 	uint8_t mode;
390*be92e5a2SBiju Das 
391*be92e5a2SBiju Das 	result = dvfs_check_error(state, err, DVFS_WRITE_MODE);
392*be92e5a2SBiju Das 	if (result == DVFS_ERROR) {
393*be92e5a2SBiju Das 		return result;
394*be92e5a2SBiju Das 	}
395*be92e5a2SBiju Das 
396*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT;
397*be92e5a2SBiju Das 	if (mode != IIC_DVFS_BIT_ICSR_WAIT) {
398*be92e5a2SBiju Das 		return result;
399*be92e5a2SBiju Das 	}
400*be92e5a2SBiju Das 
401*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_RETRANSMISSION);
402*be92e5a2SBiju Das 
403*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT;
404*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICSR, mode);
405*be92e5a2SBiju Das 
406*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICIC) | IIC_DVFS_BIT_ICIC_DTEE;
407*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICIC, mode);
408*be92e5a2SBiju Das 
409*be92e5a2SBiju Das 	*state = DVFS_SET_SLAVE_READ;
410*be92e5a2SBiju Das 
411*be92e5a2SBiju Das 	return result;
412*be92e5a2SBiju Das }
413*be92e5a2SBiju Das 
414*be92e5a2SBiju Das IIC_DVFS_FUNC(set_slave_read, enum dvfs_state_t *state, uint32_t *err,
415*be92e5a2SBiju Das 	      uint8_t slave)
416*be92e5a2SBiju Das {
417*be92e5a2SBiju Das 	uint8_t address;
418*be92e5a2SBiju Das 	int32_t result;
419*be92e5a2SBiju Das 	uint8_t mode;
420*be92e5a2SBiju Das 
421*be92e5a2SBiju Das 	result = dvfs_check_error(state, err, DVFS_WRITE_MODE);
422*be92e5a2SBiju Das 	if (result == DVFS_ERROR) {
423*be92e5a2SBiju Das 		return result;
424*be92e5a2SBiju Das 	}
425*be92e5a2SBiju Das 
426*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE;
427*be92e5a2SBiju Das 	if (mode != IIC_DVFS_BIT_ICSR_DTE) {
428*be92e5a2SBiju Das 		return result;
429*be92e5a2SBiju Das 	}
430*be92e5a2SBiju Das 
431*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE;
432*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICIC, mode);
433*be92e5a2SBiju Das 
434*be92e5a2SBiju Das 	address = ((uint8_t) (slave << 1) + DVFS_READ_MODE);
435*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICDR, address);
436*be92e5a2SBiju Das 
437*be92e5a2SBiju Das 	*state = DVFS_CHANGE_SEND_TO_RECEIVE;
438*be92e5a2SBiju Das 
439*be92e5a2SBiju Das 	return result;
440*be92e5a2SBiju Das }
441*be92e5a2SBiju Das 
442*be92e5a2SBiju Das IIC_DVFS_FUNC(change_send_to_receive, enum dvfs_state_t *state, uint32_t *err)
443*be92e5a2SBiju Das {
444*be92e5a2SBiju Das 	int32_t result;
445*be92e5a2SBiju Das 	uint8_t mode;
446*be92e5a2SBiju Das 
447*be92e5a2SBiju Das 	result = dvfs_check_error(state, err, DVFS_WRITE_MODE);
448*be92e5a2SBiju Das 	if (result == DVFS_ERROR) {
449*be92e5a2SBiju Das 		return result;
450*be92e5a2SBiju Das 	}
451*be92e5a2SBiju Das 
452*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT;
453*be92e5a2SBiju Das 	if (mode != IIC_DVFS_BIT_ICSR_WAIT) {
454*be92e5a2SBiju Das 		return result;
455*be92e5a2SBiju Das 	}
456*be92e5a2SBiju Das 
457*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_CHANGE);
458*be92e5a2SBiju Das 
459*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT;
460*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICSR, mode);
461*be92e5a2SBiju Das 
462*be92e5a2SBiju Das 	*state = DVFS_STOP_READ;
463*be92e5a2SBiju Das 
464*be92e5a2SBiju Das 	return result;
465*be92e5a2SBiju Das }
466*be92e5a2SBiju Das 
467*be92e5a2SBiju Das IIC_DVFS_FUNC(stop_read, enum dvfs_state_t *state, uint32_t *err)
468*be92e5a2SBiju Das {
469*be92e5a2SBiju Das 	int32_t result;
470*be92e5a2SBiju Das 	uint8_t mode;
471*be92e5a2SBiju Das 
472*be92e5a2SBiju Das 	result = dvfs_check_error(state, err, DVFS_READ_MODE);
473*be92e5a2SBiju Das 	if (result == DVFS_ERROR) {
474*be92e5a2SBiju Das 		return result;
475*be92e5a2SBiju Das 	}
476*be92e5a2SBiju Das 
477*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT;
478*be92e5a2SBiju Das 	if (mode != IIC_DVFS_BIT_ICSR_WAIT) {
479*be92e5a2SBiju Das 		return result;
480*be92e5a2SBiju Das 	}
481*be92e5a2SBiju Das 
482*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_STOP_READ);
483*be92e5a2SBiju Das 
484*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT;
485*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICSR, mode);
486*be92e5a2SBiju Das 
487*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICIC) | IIC_DVFS_BIT_ICIC_DTEE;
488*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICIC, mode);
489*be92e5a2SBiju Das 
490*be92e5a2SBiju Das 	*state = DVFS_READ;
491*be92e5a2SBiju Das 
492*be92e5a2SBiju Das 	return result;
493*be92e5a2SBiju Das }
494*be92e5a2SBiju Das 
495*be92e5a2SBiju Das IIC_DVFS_FUNC(read, enum dvfs_state_t *state, uint8_t *reg_data)
496*be92e5a2SBiju Das {
497*be92e5a2SBiju Das 	uint8_t mode;
498*be92e5a2SBiju Das 
499*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE;
500*be92e5a2SBiju Das 	if (mode != IIC_DVFS_BIT_ICSR_DTE) {
501*be92e5a2SBiju Das 		return DVFS_PROCESS;
502*be92e5a2SBiju Das 	}
503*be92e5a2SBiju Das 
504*be92e5a2SBiju Das 	mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE;
505*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICIC, mode);
506*be92e5a2SBiju Das 
507*be92e5a2SBiju Das 	*reg_data = mmio_read_8(IIC_DVFS_REG_ICDR);
508*be92e5a2SBiju Das 	*state = DVFS_DONE;
509*be92e5a2SBiju Das 
510*be92e5a2SBiju Das 	return DVFS_PROCESS;
511*be92e5a2SBiju Das }
512*be92e5a2SBiju Das 
513*be92e5a2SBiju Das RCAR_DVFS_API(send, uint8_t slave, uint8_t reg_addr, uint8_t reg_data)
514*be92e5a2SBiju Das {
515*be92e5a2SBiju Das 	enum dvfs_state_t state = DVFS_START;
516*be92e5a2SBiju Das 	int32_t result = DVFS_PROCESS;
517*be92e5a2SBiju Das 	uint32_t err = 0U;
518*be92e5a2SBiju Das 
519*be92e5a2SBiju Das 	mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS);
520*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCR, 0U);
521*be92e5a2SBiju Das again:
522*be92e5a2SBiju Das 	switch (state) {
523*be92e5a2SBiju Das 	case DVFS_START:
524*be92e5a2SBiju Das 		result = dvfs_start(&state);
525*be92e5a2SBiju Das 		break;
526*be92e5a2SBiju Das 	case DVFS_SET_SLAVE:
527*be92e5a2SBiju Das 		result = dvfs_set_slave(&state, &err, slave);
528*be92e5a2SBiju Das 		break;
529*be92e5a2SBiju Das 	case DVFS_WRITE_ADDR:
530*be92e5a2SBiju Das 		result = dvfs_write_addr(&state, &err, reg_addr);
531*be92e5a2SBiju Das 		break;
532*be92e5a2SBiju Das 	case DVFS_WRITE_DATA:
533*be92e5a2SBiju Das 		result = dvfs_write_data(&state, &err, reg_data);
534*be92e5a2SBiju Das 		break;
535*be92e5a2SBiju Das 	case DVFS_STOP:
536*be92e5a2SBiju Das 		result = dvfs_stop(&state, &err);
537*be92e5a2SBiju Das 		break;
538*be92e5a2SBiju Das 	case DVFS_DONE:
539*be92e5a2SBiju Das 		result = dvfs_done();
540*be92e5a2SBiju Das 		break;
541*be92e5a2SBiju Das 	default:
542*be92e5a2SBiju Das 		panic();
543*be92e5a2SBiju Das 		break;
544*be92e5a2SBiju Das 	}
545*be92e5a2SBiju Das 
546*be92e5a2SBiju Das 	if (result == DVFS_PROCESS) {
547*be92e5a2SBiju Das 		goto again;
548*be92e5a2SBiju Das 	}
549*be92e5a2SBiju Das 
550*be92e5a2SBiju Das 	return result;
551*be92e5a2SBiju Das }
552*be92e5a2SBiju Das 
553*be92e5a2SBiju Das RCAR_DVFS_API(receive, uint8_t slave, uint8_t reg, uint8_t *data)
554*be92e5a2SBiju Das {
555*be92e5a2SBiju Das 	enum dvfs_state_t state = DVFS_START;
556*be92e5a2SBiju Das 	int32_t result = DVFS_PROCESS;
557*be92e5a2SBiju Das 	uint32_t err = 0U;
558*be92e5a2SBiju Das 
559*be92e5a2SBiju Das 	mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS);
560*be92e5a2SBiju Das 	mmio_write_8(IIC_DVFS_REG_ICCR, 0U);
561*be92e5a2SBiju Das again:
562*be92e5a2SBiju Das 	switch (state) {
563*be92e5a2SBiju Das 	case DVFS_START:
564*be92e5a2SBiju Das 		result = dvfs_start(&state);
565*be92e5a2SBiju Das 		break;
566*be92e5a2SBiju Das 	case DVFS_SET_SLAVE:
567*be92e5a2SBiju Das 		result = dvfs_set_slave(&state, &err, slave);
568*be92e5a2SBiju Das 		break;
569*be92e5a2SBiju Das 	case DVFS_WRITE_ADDR:
570*be92e5a2SBiju Das 		result = dvfs_write_reg_addr_read(&state, &err, reg);
571*be92e5a2SBiju Das 		break;
572*be92e5a2SBiju Das 	case DVFS_RETRANSMIT:
573*be92e5a2SBiju Das 		result = dvfs_retransmit(&state, &err);
574*be92e5a2SBiju Das 		break;
575*be92e5a2SBiju Das 	case DVFS_SET_SLAVE_READ:
576*be92e5a2SBiju Das 		result = dvfs_set_slave_read(&state, &err, slave);
577*be92e5a2SBiju Das 		break;
578*be92e5a2SBiju Das 	case DVFS_CHANGE_SEND_TO_RECEIVE:
579*be92e5a2SBiju Das 		result = dvfs_change_send_to_receive(&state, &err);
580*be92e5a2SBiju Das 		break;
581*be92e5a2SBiju Das 	case DVFS_STOP_READ:
582*be92e5a2SBiju Das 		result = dvfs_stop_read(&state, &err);
583*be92e5a2SBiju Das 		break;
584*be92e5a2SBiju Das 	case DVFS_READ:
585*be92e5a2SBiju Das 		result = dvfs_read(&state, data);
586*be92e5a2SBiju Das 		break;
587*be92e5a2SBiju Das 	case DVFS_DONE:
588*be92e5a2SBiju Das 		result = dvfs_done();
589*be92e5a2SBiju Das 		break;
590*be92e5a2SBiju Das 	default:
591*be92e5a2SBiju Das 		panic();
592*be92e5a2SBiju Das 		break;
593*be92e5a2SBiju Das 	}
594*be92e5a2SBiju Das 
595*be92e5a2SBiju Das 	if (result == DVFS_PROCESS) {
596*be92e5a2SBiju Das 		goto again;
597*be92e5a2SBiju Das 	}
598*be92e5a2SBiju Das 
599*be92e5a2SBiju Das 	return result;
600*be92e5a2SBiju Das }
601