1*e3ec6ff4SXiaoDong Huang /* 2*e3ec6ff4SXiaoDong Huang * Copyright (c) 2024, Rockchip, Inc. All rights reserved. 3*e3ec6ff4SXiaoDong Huang * 4*e3ec6ff4SXiaoDong Huang * SPDX-License-Identifier: BSD-3-Clause 5*e3ec6ff4SXiaoDong Huang */ 6*e3ec6ff4SXiaoDong Huang 7*e3ec6ff4SXiaoDong Huang #include <assert.h> 8*e3ec6ff4SXiaoDong Huang #include <errno.h> 9*e3ec6ff4SXiaoDong Huang 10*e3ec6ff4SXiaoDong Huang #include <arch_helpers.h> 11*e3ec6ff4SXiaoDong Huang #include <bl31/bl31.h> 12*e3ec6ff4SXiaoDong Huang #include <common/debug.h> 13*e3ec6ff4SXiaoDong Huang #include <drivers/console.h> 14*e3ec6ff4SXiaoDong Huang #include <drivers/delay_timer.h> 15*e3ec6ff4SXiaoDong Huang #include <lib/mmio.h> 16*e3ec6ff4SXiaoDong Huang #include <plat/common/platform.h> 17*e3ec6ff4SXiaoDong Huang #include <platform_def.h> 18*e3ec6ff4SXiaoDong Huang 19*e3ec6ff4SXiaoDong Huang #include <plat_pm_helpers.h> 20*e3ec6ff4SXiaoDong Huang 21*e3ec6ff4SXiaoDong Huang #define ROCKCHIP_PM_REG_REGION_MEM_LEN (ROCKCHIP_PM_REG_REGION_MEM_SIZE / sizeof(uint32_t)) 22*e3ec6ff4SXiaoDong Huang 23*e3ec6ff4SXiaoDong Huang /* REG region */ 24*e3ec6ff4SXiaoDong Huang #define RGN_LEN(_rgn) (((_rgn)->end - (_rgn)->start) / (_rgn)->stride + 1) 25*e3ec6ff4SXiaoDong Huang 26*e3ec6ff4SXiaoDong Huang #ifndef ROCKCHIP_PM_REG_REGION_MEM_SIZE 27*e3ec6ff4SXiaoDong Huang #define ROCKCHIP_PM_REG_REGION_MEM_SIZE 0 28*e3ec6ff4SXiaoDong Huang #endif 29*e3ec6ff4SXiaoDong Huang 30*e3ec6ff4SXiaoDong Huang #ifdef ROCKCHIP_REG_RGN_MEM_BASE 31*e3ec6ff4SXiaoDong Huang static uint32_t *region_mem = (uint32_t *)ROCKCHIP_REG_RGN_MEM_BASE; 32*e3ec6ff4SXiaoDong Huang #else 33*e3ec6ff4SXiaoDong Huang static uint32_t region_mem[ROCKCHIP_PM_REG_REGION_MEM_LEN]; 34*e3ec6ff4SXiaoDong Huang #endif 35*e3ec6ff4SXiaoDong Huang 36*e3ec6ff4SXiaoDong Huang static int region_mem_idx; 37*e3ec6ff4SXiaoDong Huang 38*e3ec6ff4SXiaoDong Huang static int alloc_region_mem(uint32_t *buf, int max_len, 39*e3ec6ff4SXiaoDong Huang struct reg_region *rgns, uint32_t rgn_num) 40*e3ec6ff4SXiaoDong Huang { 41*e3ec6ff4SXiaoDong Huang int i; 42*e3ec6ff4SXiaoDong Huang int total_len = 0, len = 0; 43*e3ec6ff4SXiaoDong Huang struct reg_region *r = rgns; 44*e3ec6ff4SXiaoDong Huang 45*e3ec6ff4SXiaoDong Huang assert(buf && rgns && rgn_num); 46*e3ec6ff4SXiaoDong Huang 47*e3ec6ff4SXiaoDong Huang for (i = 0; i < rgn_num; i++, r++) { 48*e3ec6ff4SXiaoDong Huang if (total_len < max_len) 49*e3ec6ff4SXiaoDong Huang r->buf = &buf[total_len]; 50*e3ec6ff4SXiaoDong Huang 51*e3ec6ff4SXiaoDong Huang len = RGN_LEN(r); 52*e3ec6ff4SXiaoDong Huang total_len += len; 53*e3ec6ff4SXiaoDong Huang } 54*e3ec6ff4SXiaoDong Huang 55*e3ec6ff4SXiaoDong Huang if (total_len > max_len) { 56*e3ec6ff4SXiaoDong Huang ERROR("%s The buffer remain length:%d is too small for region:0x%x, at least %d\n", 57*e3ec6ff4SXiaoDong Huang __func__, max_len, rgns[0].start, total_len); 58*e3ec6ff4SXiaoDong Huang panic(); 59*e3ec6ff4SXiaoDong Huang } 60*e3ec6ff4SXiaoDong Huang 61*e3ec6ff4SXiaoDong Huang return total_len; 62*e3ec6ff4SXiaoDong Huang } 63*e3ec6ff4SXiaoDong Huang 64*e3ec6ff4SXiaoDong Huang /** 65*e3ec6ff4SXiaoDong Huang * Alloc memory to reg_region->buf from region_mem. 66*e3ec6ff4SXiaoDong Huang * @rgns - struct reg_region array. 67*e3ec6ff4SXiaoDong Huang * @rgn_num - struct reg_region array length. 68*e3ec6ff4SXiaoDong Huang */ 69*e3ec6ff4SXiaoDong Huang void rockchip_alloc_region_mem(struct reg_region *rgns, uint32_t rgn_num) 70*e3ec6ff4SXiaoDong Huang { 71*e3ec6ff4SXiaoDong Huang int max_len = 0, len; 72*e3ec6ff4SXiaoDong Huang 73*e3ec6ff4SXiaoDong Huang assert(rgns && rgn_num); 74*e3ec6ff4SXiaoDong Huang 75*e3ec6ff4SXiaoDong Huang max_len = ROCKCHIP_PM_REG_REGION_MEM_LEN - region_mem_idx; 76*e3ec6ff4SXiaoDong Huang 77*e3ec6ff4SXiaoDong Huang len = alloc_region_mem(region_mem + region_mem_idx, max_len, 78*e3ec6ff4SXiaoDong Huang rgns, rgn_num); 79*e3ec6ff4SXiaoDong Huang 80*e3ec6ff4SXiaoDong Huang region_mem_idx += len; 81*e3ec6ff4SXiaoDong Huang } 82*e3ec6ff4SXiaoDong Huang 83*e3ec6ff4SXiaoDong Huang /** 84*e3ec6ff4SXiaoDong Huang * Save (reg_region->start ~ reg_region->end) to reg_region->buf. 85*e3ec6ff4SXiaoDong Huang * @rgns - struct reg_region array. 86*e3ec6ff4SXiaoDong Huang * @rgn_num - struct reg_region array length. 87*e3ec6ff4SXiaoDong Huang */ 88*e3ec6ff4SXiaoDong Huang void rockchip_reg_rgn_save(struct reg_region *rgns, uint32_t rgn_num) 89*e3ec6ff4SXiaoDong Huang { 90*e3ec6ff4SXiaoDong Huang struct reg_region *r; 91*e3ec6ff4SXiaoDong Huang uint32_t addr; 92*e3ec6ff4SXiaoDong Huang int i, j; 93*e3ec6ff4SXiaoDong Huang 94*e3ec6ff4SXiaoDong Huang assert(rgns && rgn_num); 95*e3ec6ff4SXiaoDong Huang 96*e3ec6ff4SXiaoDong Huang for (i = 0; i < rgn_num; i++) { 97*e3ec6ff4SXiaoDong Huang r = &rgns[i]; 98*e3ec6ff4SXiaoDong Huang for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++) 99*e3ec6ff4SXiaoDong Huang r->buf[j] = mmio_read_32(addr); 100*e3ec6ff4SXiaoDong Huang } 101*e3ec6ff4SXiaoDong Huang } 102*e3ec6ff4SXiaoDong Huang 103*e3ec6ff4SXiaoDong Huang /** 104*e3ec6ff4SXiaoDong Huang * Restore reg_region->buf to (reg_region->start ~ reg_region->end). 105*e3ec6ff4SXiaoDong Huang * @rgns - struct reg_region array. 106*e3ec6ff4SXiaoDong Huang * @rgn_num - struct reg_region array length. 107*e3ec6ff4SXiaoDong Huang */ 108*e3ec6ff4SXiaoDong Huang void rockchip_reg_rgn_restore(struct reg_region *rgns, uint32_t rgn_num) 109*e3ec6ff4SXiaoDong Huang { 110*e3ec6ff4SXiaoDong Huang struct reg_region *r; 111*e3ec6ff4SXiaoDong Huang uint32_t addr; 112*e3ec6ff4SXiaoDong Huang int i, j; 113*e3ec6ff4SXiaoDong Huang 114*e3ec6ff4SXiaoDong Huang assert(rgns && rgn_num); 115*e3ec6ff4SXiaoDong Huang 116*e3ec6ff4SXiaoDong Huang for (i = 0; i < rgn_num; i++) { 117*e3ec6ff4SXiaoDong Huang r = &rgns[i]; 118*e3ec6ff4SXiaoDong Huang for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++) 119*e3ec6ff4SXiaoDong Huang mmio_write_32(addr, r->buf[j] | r->wmsk); 120*e3ec6ff4SXiaoDong Huang 121*e3ec6ff4SXiaoDong Huang dsb(); 122*e3ec6ff4SXiaoDong Huang } 123*e3ec6ff4SXiaoDong Huang } 124*e3ec6ff4SXiaoDong Huang 125*e3ec6ff4SXiaoDong Huang /** 126*e3ec6ff4SXiaoDong Huang * Restore reg_region->buf to (reg_region->start ~ reg_region->end) reversely. 127*e3ec6ff4SXiaoDong Huang * @rgns - struct reg_region array. 128*e3ec6ff4SXiaoDong Huang * @rgn_num - struct reg_region array length. 129*e3ec6ff4SXiaoDong Huang */ 130*e3ec6ff4SXiaoDong Huang void rockchip_reg_rgn_restore_reverse(struct reg_region *rgns, uint32_t rgn_num) 131*e3ec6ff4SXiaoDong Huang { 132*e3ec6ff4SXiaoDong Huang struct reg_region *r; 133*e3ec6ff4SXiaoDong Huang uint32_t addr; 134*e3ec6ff4SXiaoDong Huang int i, j; 135*e3ec6ff4SXiaoDong Huang 136*e3ec6ff4SXiaoDong Huang assert(rgns && rgn_num); 137*e3ec6ff4SXiaoDong Huang 138*e3ec6ff4SXiaoDong Huang for (i = rgn_num - 1; i >= 0; i--) { 139*e3ec6ff4SXiaoDong Huang r = &rgns[i]; 140*e3ec6ff4SXiaoDong Huang j = RGN_LEN(r) - 1; 141*e3ec6ff4SXiaoDong Huang for (addr = r->end; addr >= r->start; addr -= r->stride, j--) 142*e3ec6ff4SXiaoDong Huang mmio_write_32(addr, r->buf[j] | r->wmsk); 143*e3ec6ff4SXiaoDong Huang 144*e3ec6ff4SXiaoDong Huang dsb(); 145*e3ec6ff4SXiaoDong Huang } 146*e3ec6ff4SXiaoDong Huang } 147*e3ec6ff4SXiaoDong Huang 148*e3ec6ff4SXiaoDong Huang static void rockchip_print_hex(uint32_t val) 149*e3ec6ff4SXiaoDong Huang { 150*e3ec6ff4SXiaoDong Huang int i; 151*e3ec6ff4SXiaoDong Huang unsigned char tmp; 152*e3ec6ff4SXiaoDong Huang 153*e3ec6ff4SXiaoDong Huang putchar('0'); 154*e3ec6ff4SXiaoDong Huang putchar('x'); 155*e3ec6ff4SXiaoDong Huang for (i = 0; i < 8; val <<= 4, ++i) { 156*e3ec6ff4SXiaoDong Huang tmp = (val & 0xf0000000) >> 28; 157*e3ec6ff4SXiaoDong Huang if (tmp < 10) 158*e3ec6ff4SXiaoDong Huang putchar('0' + tmp); 159*e3ec6ff4SXiaoDong Huang else 160*e3ec6ff4SXiaoDong Huang putchar('a' + tmp - 10); 161*e3ec6ff4SXiaoDong Huang } 162*e3ec6ff4SXiaoDong Huang } 163*e3ec6ff4SXiaoDong Huang 164*e3ec6ff4SXiaoDong Huang /** 165*e3ec6ff4SXiaoDong Huang * Dump registers (base + start_offset ~ base + end_offset) 166*e3ec6ff4SXiaoDong Huang * @base - the base addr of the register. 167*e3ec6ff4SXiaoDong Huang * @start_offset - the start offset to dump. 168*e3ec6ff4SXiaoDong Huang * @end_offset - the end offset to dump. 169*e3ec6ff4SXiaoDong Huang * @stride - the stride of the registers. 170*e3ec6ff4SXiaoDong Huang */ 171*e3ec6ff4SXiaoDong Huang void rockchip_regs_dump(uint32_t base, 172*e3ec6ff4SXiaoDong Huang uint32_t start_offset, 173*e3ec6ff4SXiaoDong Huang uint32_t end_offset, 174*e3ec6ff4SXiaoDong Huang uint32_t stride) 175*e3ec6ff4SXiaoDong Huang { 176*e3ec6ff4SXiaoDong Huang uint32_t i; 177*e3ec6ff4SXiaoDong Huang 178*e3ec6ff4SXiaoDong Huang for (i = start_offset; i <= end_offset; i += stride) { 179*e3ec6ff4SXiaoDong Huang if ((i - start_offset) % 16 == 0) { 180*e3ec6ff4SXiaoDong Huang putchar('\n'); 181*e3ec6ff4SXiaoDong Huang rockchip_print_hex(base + i); 182*e3ec6ff4SXiaoDong Huang putchar(':'); 183*e3ec6ff4SXiaoDong Huang putchar(' '); 184*e3ec6ff4SXiaoDong Huang putchar(' '); 185*e3ec6ff4SXiaoDong Huang putchar(' '); 186*e3ec6ff4SXiaoDong Huang putchar(' '); 187*e3ec6ff4SXiaoDong Huang } 188*e3ec6ff4SXiaoDong Huang rockchip_print_hex(mmio_read_32(base + i)); 189*e3ec6ff4SXiaoDong Huang putchar(' '); 190*e3ec6ff4SXiaoDong Huang putchar(' '); 191*e3ec6ff4SXiaoDong Huang putchar(' '); 192*e3ec6ff4SXiaoDong Huang putchar(' '); 193*e3ec6ff4SXiaoDong Huang } 194*e3ec6ff4SXiaoDong Huang putchar('\n'); 195*e3ec6ff4SXiaoDong Huang } 196*e3ec6ff4SXiaoDong Huang 197*e3ec6ff4SXiaoDong Huang /** 198*e3ec6ff4SXiaoDong Huang * Dump reg regions 199*e3ec6ff4SXiaoDong Huang * @rgns - struct reg_region array. 200*e3ec6ff4SXiaoDong Huang * @rgn_num - struct reg_region array length. 201*e3ec6ff4SXiaoDong Huang */ 202*e3ec6ff4SXiaoDong Huang void rockchip_dump_reg_rgns(struct reg_region *rgns, uint32_t rgn_num) 203*e3ec6ff4SXiaoDong Huang { 204*e3ec6ff4SXiaoDong Huang struct reg_region *r; 205*e3ec6ff4SXiaoDong Huang int i; 206*e3ec6ff4SXiaoDong Huang 207*e3ec6ff4SXiaoDong Huang assert(rgns && rgn_num); 208*e3ec6ff4SXiaoDong Huang 209*e3ec6ff4SXiaoDong Huang for (i = 0; i < rgn_num; i++) { 210*e3ec6ff4SXiaoDong Huang r = &rgns[i]; 211*e3ec6ff4SXiaoDong Huang rockchip_regs_dump(0x0, r->start, r->end, r->stride); 212*e3ec6ff4SXiaoDong Huang } 213*e3ec6ff4SXiaoDong Huang } 214