123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- /*
- * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <assert.h>
- #include <errno.h>
- #include <arch_helpers.h>
- #include <bl31/bl31.h>
- #include <common/debug.h>
- #include <drivers/console.h>
- #include <drivers/delay_timer.h>
- #include <lib/mmio.h>
- #include <plat/common/platform.h>
- #include <platform_def.h>
- #include <plat_pm_helpers.h>
- #define ROCKCHIP_PM_REG_REGION_MEM_LEN (ROCKCHIP_PM_REG_REGION_MEM_SIZE / sizeof(uint32_t))
- /* REG region */
- #define RGN_LEN(_rgn) (((_rgn)->end - (_rgn)->start) / (_rgn)->stride + 1)
- #ifndef ROCKCHIP_PM_REG_REGION_MEM_SIZE
- #define ROCKCHIP_PM_REG_REGION_MEM_SIZE 0
- #endif
- #ifdef ROCKCHIP_REG_RGN_MEM_BASE
- static uint32_t *region_mem = (uint32_t *)ROCKCHIP_REG_RGN_MEM_BASE;
- #else
- static uint32_t region_mem[ROCKCHIP_PM_REG_REGION_MEM_LEN];
- #endif
- static int region_mem_idx;
- static int alloc_region_mem(uint32_t *buf, int max_len,
- struct reg_region *rgns, uint32_t rgn_num)
- {
- int i;
- int total_len = 0, len = 0;
- struct reg_region *r = rgns;
- assert(buf && rgns && rgn_num);
- for (i = 0; i < rgn_num; i++, r++) {
- if (total_len < max_len)
- r->buf = &buf[total_len];
- len = RGN_LEN(r);
- total_len += len;
- }
- if (total_len > max_len) {
- ERROR("%s The buffer remain length:%d is too small for region:0x%x, at least %d\n",
- __func__, max_len, rgns[0].start, total_len);
- panic();
- }
- return total_len;
- }
- /**
- * Alloc memory to reg_region->buf from region_mem.
- * @rgns - struct reg_region array.
- * @rgn_num - struct reg_region array length.
- */
- void rockchip_alloc_region_mem(struct reg_region *rgns, uint32_t rgn_num)
- {
- int max_len = 0, len;
- assert(rgns && rgn_num);
- max_len = ROCKCHIP_PM_REG_REGION_MEM_LEN - region_mem_idx;
- len = alloc_region_mem(region_mem + region_mem_idx, max_len,
- rgns, rgn_num);
- region_mem_idx += len;
- }
- /**
- * Save (reg_region->start ~ reg_region->end) to reg_region->buf.
- * @rgns - struct reg_region array.
- * @rgn_num - struct reg_region array length.
- */
- void rockchip_reg_rgn_save(struct reg_region *rgns, uint32_t rgn_num)
- {
- struct reg_region *r;
- uint32_t addr;
- int i, j;
- assert(rgns && rgn_num);
- for (i = 0; i < rgn_num; i++) {
- r = &rgns[i];
- for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++)
- r->buf[j] = mmio_read_32(addr);
- }
- }
- /**
- * Restore reg_region->buf to (reg_region->start ~ reg_region->end).
- * @rgns - struct reg_region array.
- * @rgn_num - struct reg_region array length.
- */
- void rockchip_reg_rgn_restore(struct reg_region *rgns, uint32_t rgn_num)
- {
- struct reg_region *r;
- uint32_t addr;
- int i, j;
- assert(rgns && rgn_num);
- for (i = 0; i < rgn_num; i++) {
- r = &rgns[i];
- for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++)
- mmio_write_32(addr, r->buf[j] | r->wmsk);
- dsb();
- }
- }
- /**
- * Restore reg_region->buf to (reg_region->start ~ reg_region->end) reversely.
- * @rgns - struct reg_region array.
- * @rgn_num - struct reg_region array length.
- */
- void rockchip_reg_rgn_restore_reverse(struct reg_region *rgns, uint32_t rgn_num)
- {
- struct reg_region *r;
- uint32_t addr;
- int i, j;
- assert(rgns && rgn_num);
- for (i = rgn_num - 1; i >= 0; i--) {
- r = &rgns[i];
- j = RGN_LEN(r) - 1;
- for (addr = r->end; addr >= r->start; addr -= r->stride, j--)
- mmio_write_32(addr, r->buf[j] | r->wmsk);
- dsb();
- }
- }
- static void rockchip_print_hex(uint32_t val)
- {
- int i;
- unsigned char tmp;
- putchar('0');
- putchar('x');
- for (i = 0; i < 8; val <<= 4, ++i) {
- tmp = (val & 0xf0000000) >> 28;
- if (tmp < 10)
- putchar('0' + tmp);
- else
- putchar('a' + tmp - 10);
- }
- }
- /**
- * Dump registers (base + start_offset ~ base + end_offset)
- * @base - the base addr of the register.
- * @start_offset - the start offset to dump.
- * @end_offset - the end offset to dump.
- * @stride - the stride of the registers.
- */
- void rockchip_regs_dump(uint32_t base,
- uint32_t start_offset,
- uint32_t end_offset,
- uint32_t stride)
- {
- uint32_t i;
- for (i = start_offset; i <= end_offset; i += stride) {
- if ((i - start_offset) % 16 == 0) {
- putchar('\n');
- rockchip_print_hex(base + i);
- putchar(':');
- putchar(' ');
- putchar(' ');
- putchar(' ');
- putchar(' ');
- }
- rockchip_print_hex(mmio_read_32(base + i));
- putchar(' ');
- putchar(' ');
- putchar(' ');
- putchar(' ');
- }
- putchar('\n');
- }
- /**
- * Dump reg regions
- * @rgns - struct reg_region array.
- * @rgn_num - struct reg_region array length.
- */
- void rockchip_dump_reg_rgns(struct reg_region *rgns, uint32_t rgn_num)
- {
- struct reg_region *r;
- int i;
- assert(rgns && rgn_num);
- for (i = 0; i < rgn_num; i++) {
- r = &rgns[i];
- rockchip_regs_dump(0x0, r->start, r->end, r->stride);
- }
- }
|