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