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