xref: /aosp_15_r20/external/arm-trusted-firmware/drivers/allwinner/sunxi_rsb.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <errno.h>
8*54fd6939SJiyong Park 
9*54fd6939SJiyong Park #include <common/debug.h>
10*54fd6939SJiyong Park #include <drivers/delay_timer.h>
11*54fd6939SJiyong Park #include <lib/mmio.h>
12*54fd6939SJiyong Park 
13*54fd6939SJiyong Park #include <sunxi_mmap.h>
14*54fd6939SJiyong Park 
15*54fd6939SJiyong Park #define RSB_CTRL	0x00
16*54fd6939SJiyong Park #define RSB_CCR		0x04
17*54fd6939SJiyong Park #define RSB_INTE	0x08
18*54fd6939SJiyong Park #define RSB_STAT	0x0c
19*54fd6939SJiyong Park #define RSB_DADDR0	0x10
20*54fd6939SJiyong Park #define RSB_DLEN	0x18
21*54fd6939SJiyong Park #define RSB_DATA0	0x1c
22*54fd6939SJiyong Park #define RSB_LCR		0x24
23*54fd6939SJiyong Park #define RSB_PMCR	0x28
24*54fd6939SJiyong Park #define RSB_CMD		0x2c
25*54fd6939SJiyong Park #define RSB_SADDR	0x30
26*54fd6939SJiyong Park 
27*54fd6939SJiyong Park #define RSBCMD_SRTA	0xE8
28*54fd6939SJiyong Park #define RSBCMD_RD8	0x8B
29*54fd6939SJiyong Park #define RSBCMD_RD16	0x9C
30*54fd6939SJiyong Park #define RSBCMD_RD32	0xA6
31*54fd6939SJiyong Park #define RSBCMD_WR8	0x4E
32*54fd6939SJiyong Park #define RSBCMD_WR16	0x59
33*54fd6939SJiyong Park #define RSBCMD_WR32	0x63
34*54fd6939SJiyong Park 
35*54fd6939SJiyong Park #define MAX_TRIES	100000
36*54fd6939SJiyong Park 
rsb_wait_bit(const char * desc,unsigned int offset,uint32_t mask)37*54fd6939SJiyong Park static int rsb_wait_bit(const char *desc, unsigned int offset, uint32_t mask)
38*54fd6939SJiyong Park {
39*54fd6939SJiyong Park 	uint32_t reg, tries = MAX_TRIES;
40*54fd6939SJiyong Park 
41*54fd6939SJiyong Park 	do
42*54fd6939SJiyong Park 		reg = mmio_read_32(SUNXI_R_RSB_BASE + offset);
43*54fd6939SJiyong Park 	while ((reg & mask) && --tries);	/* transaction in progress */
44*54fd6939SJiyong Park 	if (reg & mask) {
45*54fd6939SJiyong Park 		ERROR("%s: timed out\n", desc);
46*54fd6939SJiyong Park 		return -ETIMEDOUT;
47*54fd6939SJiyong Park 	}
48*54fd6939SJiyong Park 
49*54fd6939SJiyong Park 	return 0;
50*54fd6939SJiyong Park }
51*54fd6939SJiyong Park 
rsb_wait_stat(const char * desc)52*54fd6939SJiyong Park static int rsb_wait_stat(const char *desc)
53*54fd6939SJiyong Park {
54*54fd6939SJiyong Park 	uint32_t reg;
55*54fd6939SJiyong Park 	int ret = rsb_wait_bit(desc, RSB_CTRL, BIT(7));
56*54fd6939SJiyong Park 
57*54fd6939SJiyong Park 	if (ret)
58*54fd6939SJiyong Park 		return ret;
59*54fd6939SJiyong Park 
60*54fd6939SJiyong Park 	reg = mmio_read_32(SUNXI_R_RSB_BASE + RSB_STAT);
61*54fd6939SJiyong Park 	if (reg == 0x01)
62*54fd6939SJiyong Park 		return 0;
63*54fd6939SJiyong Park 
64*54fd6939SJiyong Park 	ERROR("%s: 0x%x\n", desc, reg);
65*54fd6939SJiyong Park 	return -reg;
66*54fd6939SJiyong Park }
67*54fd6939SJiyong Park 
68*54fd6939SJiyong Park /* Initialize the RSB controller. */
rsb_init_controller(void)69*54fd6939SJiyong Park int rsb_init_controller(void)
70*54fd6939SJiyong Park {
71*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x01); /* soft reset */
72*54fd6939SJiyong Park 
73*54fd6939SJiyong Park 	return rsb_wait_bit("RSB: reset controller", RSB_CTRL, BIT(0));
74*54fd6939SJiyong Park }
75*54fd6939SJiyong Park 
rsb_read(uint8_t rt_addr,uint8_t reg_addr)76*54fd6939SJiyong Park int rsb_read(uint8_t rt_addr, uint8_t reg_addr)
77*54fd6939SJiyong Park {
78*54fd6939SJiyong Park 	int ret;
79*54fd6939SJiyong Park 
80*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_RD8); /* read a byte */
81*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16);
82*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr);
83*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */
84*54fd6939SJiyong Park 
85*54fd6939SJiyong Park 	ret = rsb_wait_stat("RSB: read command");
86*54fd6939SJiyong Park 	if (ret)
87*54fd6939SJiyong Park 		return ret;
88*54fd6939SJiyong Park 
89*54fd6939SJiyong Park 	return mmio_read_32(SUNXI_R_RSB_BASE + RSB_DATA0) & 0xff; /* result */
90*54fd6939SJiyong Park }
91*54fd6939SJiyong Park 
rsb_write(uint8_t rt_addr,uint8_t reg_addr,uint8_t value)92*54fd6939SJiyong Park int rsb_write(uint8_t rt_addr, uint8_t reg_addr, uint8_t value)
93*54fd6939SJiyong Park {
94*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_WR8);	/* byte write */
95*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16);
96*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr);
97*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_DATA0, value);
98*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */
99*54fd6939SJiyong Park 
100*54fd6939SJiyong Park 	return rsb_wait_stat("RSB: write command");
101*54fd6939SJiyong Park }
102*54fd6939SJiyong Park 
rsb_set_device_mode(uint32_t device_mode)103*54fd6939SJiyong Park int rsb_set_device_mode(uint32_t device_mode)
104*54fd6939SJiyong Park {
105*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_PMCR,
106*54fd6939SJiyong Park 		      (device_mode & 0x00ffffff) | BIT(31));
107*54fd6939SJiyong Park 
108*54fd6939SJiyong Park 	return rsb_wait_bit("RSB: set device to RSB", RSB_PMCR, BIT(31));
109*54fd6939SJiyong Park }
110*54fd6939SJiyong Park 
rsb_set_bus_speed(uint32_t source_freq,uint32_t bus_freq)111*54fd6939SJiyong Park int rsb_set_bus_speed(uint32_t source_freq, uint32_t bus_freq)
112*54fd6939SJiyong Park {
113*54fd6939SJiyong Park 	uint32_t reg;
114*54fd6939SJiyong Park 
115*54fd6939SJiyong Park 	if (bus_freq == 0)
116*54fd6939SJiyong Park 		return -EINVAL;
117*54fd6939SJiyong Park 
118*54fd6939SJiyong Park 	reg = source_freq / bus_freq;
119*54fd6939SJiyong Park 	if (reg < 2)
120*54fd6939SJiyong Park 		return -EINVAL;
121*54fd6939SJiyong Park 
122*54fd6939SJiyong Park 	reg = reg / 2 - 1;
123*54fd6939SJiyong Park 	reg |= (1U << 8);		/* one cycle of CD output delay */
124*54fd6939SJiyong Park 
125*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CCR, reg);
126*54fd6939SJiyong Park 
127*54fd6939SJiyong Park 	return 0;
128*54fd6939SJiyong Park }
129*54fd6939SJiyong Park 
130*54fd6939SJiyong Park /* Initialize the RSB PMIC connection. */
rsb_assign_runtime_address(uint16_t hw_addr,uint8_t rt_addr)131*54fd6939SJiyong Park int rsb_assign_runtime_address(uint16_t hw_addr, uint8_t rt_addr)
132*54fd6939SJiyong Park {
133*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, hw_addr | (rt_addr << 16));
134*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_SRTA);
135*54fd6939SJiyong Park 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);
136*54fd6939SJiyong Park 
137*54fd6939SJiyong Park 	return rsb_wait_stat("RSB: set run-time address");
138*54fd6939SJiyong Park }
139