xref: /rk3399_ARM-atf/drivers/allwinner/sunxi_rsb.c (revision 9a207532f8216bf83fed0891fed9ed0bc72ca450)
1103f19f0SAndre Przywara /*
2103f19f0SAndre Przywara  * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved.
3103f19f0SAndre Przywara  *
4103f19f0SAndre Przywara  * SPDX-License-Identifier: BSD-3-Clause
5103f19f0SAndre Przywara  */
6103f19f0SAndre Przywara 
7103f19f0SAndre Przywara #include <errno.h>
8*09d40e0eSAntonio Nino Diaz 
9*09d40e0eSAntonio Nino Diaz #include <common/debug.h>
10*09d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h>
11*09d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
12*09d40e0eSAntonio Nino Diaz 
13103f19f0SAndre Przywara #include <sunxi_mmap.h>
14103f19f0SAndre Przywara 
15103f19f0SAndre Przywara #define RSB_CTRL	0x00
16103f19f0SAndre Przywara #define RSB_CCR		0x04
17103f19f0SAndre Przywara #define RSB_INTE	0x08
18103f19f0SAndre Przywara #define RSB_STAT	0x0c
19103f19f0SAndre Przywara #define RSB_DADDR0	0x10
20103f19f0SAndre Przywara #define RSB_DLEN	0x18
21103f19f0SAndre Przywara #define RSB_DATA0	0x1c
22103f19f0SAndre Przywara #define RSB_LCR		0x24
23103f19f0SAndre Przywara #define RSB_PMCR	0x28
24103f19f0SAndre Przywara #define RSB_CMD		0x2c
25103f19f0SAndre Przywara #define RSB_SADDR	0x30
26103f19f0SAndre Przywara 
27103f19f0SAndre Przywara #define RSBCMD_SRTA	0xE8
28103f19f0SAndre Przywara #define RSBCMD_RD8	0x8B
29103f19f0SAndre Przywara #define RSBCMD_RD16	0x9C
30103f19f0SAndre Przywara #define RSBCMD_RD32	0xA6
31103f19f0SAndre Przywara #define RSBCMD_WR8	0x4E
32103f19f0SAndre Przywara #define RSBCMD_WR16	0x59
33103f19f0SAndre Przywara #define RSBCMD_WR32	0x63
34103f19f0SAndre Przywara 
35103f19f0SAndre Przywara #define MAX_TRIES	100000
36103f19f0SAndre Przywara 
rsb_wait_bit(const char * desc,unsigned int offset,uint32_t mask)37103f19f0SAndre Przywara static int rsb_wait_bit(const char *desc, unsigned int offset, uint32_t mask)
38103f19f0SAndre Przywara {
39103f19f0SAndre Przywara 	uint32_t reg, tries = MAX_TRIES;
40103f19f0SAndre Przywara 
41103f19f0SAndre Przywara 	do
42103f19f0SAndre Przywara 		reg = mmio_read_32(SUNXI_R_RSB_BASE + offset);
43103f19f0SAndre Przywara 	while ((reg & mask) && --tries);	/* transaction in progress */
44103f19f0SAndre Przywara 	if (reg & mask) {
45103f19f0SAndre Przywara 		ERROR("%s: timed out\n", desc);
46103f19f0SAndre Przywara 		return -ETIMEDOUT;
47103f19f0SAndre Przywara 	}
48103f19f0SAndre Przywara 
49103f19f0SAndre Przywara 	return 0;
50103f19f0SAndre Przywara }
51103f19f0SAndre Przywara 
rsb_wait_stat(const char * desc)52103f19f0SAndre Przywara static int rsb_wait_stat(const char *desc)
53103f19f0SAndre Przywara {
54103f19f0SAndre Przywara 	uint32_t reg;
55103f19f0SAndre Przywara 	int ret = rsb_wait_bit(desc, RSB_CTRL, BIT(7));
56103f19f0SAndre Przywara 
57103f19f0SAndre Przywara 	if (ret)
58103f19f0SAndre Przywara 		return ret;
59103f19f0SAndre Przywara 
60103f19f0SAndre Przywara 	reg = mmio_read_32(SUNXI_R_RSB_BASE + RSB_STAT);
61103f19f0SAndre Przywara 	if (reg == 0x01)
62103f19f0SAndre Przywara 		return 0;
63103f19f0SAndre Przywara 
64103f19f0SAndre Przywara 	ERROR("%s: 0x%x\n", desc, reg);
65103f19f0SAndre Przywara 	return -reg;
66103f19f0SAndre Przywara }
67103f19f0SAndre Przywara 
68103f19f0SAndre Przywara /* Initialize the RSB controller. */
rsb_init_controller(void)69103f19f0SAndre Przywara int rsb_init_controller(void)
70103f19f0SAndre Przywara {
71103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x01); /* soft reset */
72103f19f0SAndre Przywara 
73103f19f0SAndre Przywara 	return rsb_wait_bit("RSB: reset controller", RSB_CTRL, BIT(0));
74103f19f0SAndre Przywara }
75103f19f0SAndre Przywara 
rsb_read(uint8_t rt_addr,uint8_t reg_addr)76103f19f0SAndre Przywara int rsb_read(uint8_t rt_addr, uint8_t reg_addr)
77103f19f0SAndre Przywara {
78103f19f0SAndre Przywara 	int ret;
79103f19f0SAndre Przywara 
80103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_RD8); /* read a byte */
81103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16);
82103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr);
83103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */
84103f19f0SAndre Przywara 
85103f19f0SAndre Przywara 	ret = rsb_wait_stat("RSB: read command");
86103f19f0SAndre Przywara 	if (ret)
87103f19f0SAndre Przywara 		return ret;
88103f19f0SAndre Przywara 
89103f19f0SAndre Przywara 	return mmio_read_32(SUNXI_R_RSB_BASE + RSB_DATA0) & 0xff; /* result */
90103f19f0SAndre Przywara }
91103f19f0SAndre Przywara 
rsb_write(uint8_t rt_addr,uint8_t reg_addr,uint8_t value)92103f19f0SAndre Przywara int rsb_write(uint8_t rt_addr, uint8_t reg_addr, uint8_t value)
93103f19f0SAndre Przywara {
94103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_WR8);	/* byte write */
95103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16);
96103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr);
97103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_DATA0, value);
98103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */
99103f19f0SAndre Przywara 
100103f19f0SAndre Przywara 	return rsb_wait_stat("RSB: write command");
101103f19f0SAndre Przywara }
102103f19f0SAndre Przywara 
rsb_set_device_mode(uint32_t device_mode)103103f19f0SAndre Przywara int rsb_set_device_mode(uint32_t device_mode)
104103f19f0SAndre Przywara {
105103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_PMCR,
106103f19f0SAndre Przywara 		      (device_mode & 0x00ffffff) | BIT(31));
107103f19f0SAndre Przywara 
108103f19f0SAndre Przywara 	return rsb_wait_bit("RSB: set device to RSB", RSB_PMCR, BIT(31));
109103f19f0SAndre Przywara }
110103f19f0SAndre Przywara 
rsb_set_bus_speed(uint32_t source_freq,uint32_t bus_freq)111103f19f0SAndre Przywara int rsb_set_bus_speed(uint32_t source_freq, uint32_t bus_freq)
112103f19f0SAndre Przywara {
113103f19f0SAndre Przywara 	uint32_t reg;
114103f19f0SAndre Przywara 
115103f19f0SAndre Przywara 	if (bus_freq == 0)
116103f19f0SAndre Przywara 		return -EINVAL;
117103f19f0SAndre Przywara 
118103f19f0SAndre Przywara 	reg = source_freq / bus_freq;
119103f19f0SAndre Przywara 	if (reg < 2)
120103f19f0SAndre Przywara 		return -EINVAL;
121103f19f0SAndre Przywara 
122103f19f0SAndre Przywara 	reg = reg / 2 - 1;
123103f19f0SAndre Przywara 	reg |= (1U << 8);		/* one cycle of CD output delay */
124103f19f0SAndre Przywara 
125103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CCR, reg);
126103f19f0SAndre Przywara 
127103f19f0SAndre Przywara 	return 0;
128103f19f0SAndre Przywara }
129103f19f0SAndre Przywara 
130103f19f0SAndre Przywara /* Initialize the RSB PMIC connection. */
rsb_assign_runtime_address(uint16_t hw_addr,uint8_t rt_addr)131103f19f0SAndre Przywara int rsb_assign_runtime_address(uint16_t hw_addr, uint8_t rt_addr)
132103f19f0SAndre Przywara {
133103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, hw_addr | (rt_addr << 16));
134103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_SRTA);
135103f19f0SAndre Przywara 	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);
136103f19f0SAndre Przywara 
137103f19f0SAndre Przywara 	return rsb_wait_stat("RSB: set run-time address");
138103f19f0SAndre Przywara }
139