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