123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- /*
- * Copyright (C) 2016 Marvell International Ltd.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- * https://spdx.org/licenses
- */
- #include <common/debug.h>
- #include <lib/mmio.h>
- #include <io_addr_dec.h>
- #include <plat_marvell.h>
- #define MVEBU_DEC_WIN_CTRL_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
- (win) * (off))
- #define MVEBU_DEC_WIN_BASE_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
- (win) * (off) + 0x4)
- #define MVEBU_DEC_WIN_REMAP_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
- (win) * (off) + 0x8)
- #define MVEBU_DEC_WIN_CTRL_SIZE_OFF (16)
- #define MVEBU_DEC_WIN_ENABLE (0x1)
- #define MVEBU_DEC_WIN_CTRL_ATTR_OFF (8)
- #define MVEBU_DEC_WIN_CTRL_TARGET_OFF (4)
- #define MVEBU_DEC_WIN_CTRL_EN_OFF (0)
- #define MVEBU_DEC_WIN_BASE_OFF (16)
- #define MVEBU_WIN_BASE_SIZE_ALIGNMENT (0x10000)
- /* There are up to 14 IO unit which need address decode in Armada-3700 */
- #define IO_UNIT_NUM_MAX (14)
- #define MVEBU_MAX_ADDRSS_4GB (0x100000000ULL)
- static void set_io_addr_dec_win(int win_id, uintptr_t base_addr,
- uintptr_t win_size,
- struct dec_win_config *dec_win)
- {
- uint32_t ctrl = 0;
- uint32_t base = 0;
- /* set size */
- ctrl = ((win_size / MVEBU_WIN_BASE_SIZE_ALIGNMENT) - 1) <<
- MVEBU_DEC_WIN_CTRL_SIZE_OFF;
- /* set attr according to IO decode window */
- ctrl |= dec_win->win_attr << MVEBU_DEC_WIN_CTRL_ATTR_OFF;
- /* set target */
- ctrl |= DRAM_CPU_DEC_TARGET_NUM << MVEBU_DEC_WIN_CTRL_TARGET_OFF;
- /* set base */
- base = (base_addr / MVEBU_WIN_BASE_SIZE_ALIGNMENT) <<
- MVEBU_DEC_WIN_BASE_OFF;
- /* set base address*/
- mmio_write_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
- win_id, dec_win->win_offset),
- base);
- /* set remap window, some unit does not have remap window */
- if (win_id < dec_win->max_remap)
- mmio_write_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
- win_id, dec_win->win_offset), base);
- /* set control register */
- mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
- win_id, dec_win->win_offset), ctrl);
- /* enable the address decode window at last to make it effective */
- ctrl |= MVEBU_DEC_WIN_ENABLE << MVEBU_DEC_WIN_CTRL_EN_OFF;
- mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
- win_id, dec_win->win_offset), ctrl);
- INFO("set_io_addr_dec %d result: ctrl(0x%x) base(0x%x) remap(0x%x)\n",
- win_id, mmio_read_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
- win_id, dec_win->win_offset)),
- mmio_read_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
- win_id, dec_win->win_offset)),
- (win_id < dec_win->max_remap) ?
- mmio_read_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
- win_id, dec_win->win_offset)) : 0);
- }
- /* Set io decode window */
- static int set_io_addr_dec(struct dram_win_map *win_map,
- struct dec_win_config *dec_win)
- {
- struct dram_win *win;
- int id;
- /* disable all windows first */
- for (id = 0; id < dec_win->max_dram_win; id++)
- mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, id,
- dec_win->win_offset), 0);
- /* configure IO decode windows for DRAM, inheritate DRAM size,
- * base and target from CPU-DRAM decode window and others
- * from hard coded IO decode window settings array.
- */
- if (win_map->dram_win_num > dec_win->max_dram_win) {
- /*
- * If cpu dram windows number exceeds the io decode windows
- * max number, then fill the first io decode window
- * with base(0) and size(4GB).
- */
- set_io_addr_dec_win(0, 0, MVEBU_MAX_ADDRSS_4GB, dec_win);
- return 0;
- }
- for (id = 0; id < win_map->dram_win_num; id++, win++) {
- win = &win_map->dram_windows[id];
- set_io_addr_dec_win(id, win->base_addr, win->win_size, dec_win);
- }
- return 0;
- }
- /*
- * init_io_addr_dec
- *
- * This function initializes io address decoder windows by
- * cpu dram window mapping information
- *
- * @input: N/A
- * - dram_wins_map: cpu dram windows mapping
- * - io_dec_config: io address decoder windows configuration
- * - io_unit_num: io address decoder unit number
- * @output: N/A
- *
- * @return: 0 on success and others on failure
- */
- int init_io_addr_dec(struct dram_win_map *dram_wins_map,
- struct dec_win_config *io_dec_config, uint32_t io_unit_num)
- {
- int32_t index;
- struct dec_win_config *io_dec_win;
- int32_t ret;
- INFO("Initializing IO address decode windows\n");
- if (io_dec_config == NULL || io_unit_num == 0) {
- ERROR("No IO address decoder windows configurations!\n");
- return -1;
- }
- if (io_unit_num > IO_UNIT_NUM_MAX) {
- ERROR("IO address decoder windows number %d is over max %d\n",
- io_unit_num, IO_UNIT_NUM_MAX);
- return -1;
- }
- if (dram_wins_map == NULL) {
- ERROR("No cpu dram decoder windows map!\n");
- return -1;
- }
- for (index = 0; index < dram_wins_map->dram_win_num; index++)
- INFO("DRAM mapping %d base(0x%lx) size(0x%lx)\n",
- index, dram_wins_map->dram_windows[index].base_addr,
- dram_wins_map->dram_windows[index].win_size);
- /* Set address decode window for each IO */
- for (index = 0; index < io_unit_num; index++) {
- io_dec_win = io_dec_config + index;
- ret = set_io_addr_dec(dram_wins_map, io_dec_win);
- if (ret) {
- ERROR("Failed to set IO address decode\n");
- return -1;
- }
- INFO("Set IO decode window successfully, base(0x%x)"
- " win_attr(%x) max_dram_win(%d) max_remap(%d)"
- " win_offset(%d)\n", io_dec_win->dec_reg_base,
- io_dec_win->win_attr, io_dec_win->max_dram_win,
- io_dec_win->max_remap, io_dec_win->win_offset);
- }
- return 0;
- }
|