1 /* 2 * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <errno.h> 8 9 #include <common/debug.h> 10 #include <drivers/delay_timer.h> 11 #include <lib/mmio.h> 12 13 #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 37 static 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 52 static 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. */ 69 int 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 76 int 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 92 int 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 103 int 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 111 int 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. */ 131 int 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 } 139