1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (C) 2016 Marvell International Ltd. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu * https://spdx.org/licenses 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <common/debug.h> 9*91f16700Schasinglulu #include <lib/mmio.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <io_addr_dec.h> 12*91f16700Schasinglulu #include <plat_marvell.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu #define MVEBU_DEC_WIN_CTRL_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \ 15*91f16700Schasinglulu (win) * (off)) 16*91f16700Schasinglulu #define MVEBU_DEC_WIN_BASE_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \ 17*91f16700Schasinglulu (win) * (off) + 0x4) 18*91f16700Schasinglulu #define MVEBU_DEC_WIN_REMAP_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \ 19*91f16700Schasinglulu (win) * (off) + 0x8) 20*91f16700Schasinglulu 21*91f16700Schasinglulu #define MVEBU_DEC_WIN_CTRL_SIZE_OFF (16) 22*91f16700Schasinglulu #define MVEBU_DEC_WIN_ENABLE (0x1) 23*91f16700Schasinglulu #define MVEBU_DEC_WIN_CTRL_ATTR_OFF (8) 24*91f16700Schasinglulu #define MVEBU_DEC_WIN_CTRL_TARGET_OFF (4) 25*91f16700Schasinglulu #define MVEBU_DEC_WIN_CTRL_EN_OFF (0) 26*91f16700Schasinglulu #define MVEBU_DEC_WIN_BASE_OFF (16) 27*91f16700Schasinglulu 28*91f16700Schasinglulu #define MVEBU_WIN_BASE_SIZE_ALIGNMENT (0x10000) 29*91f16700Schasinglulu 30*91f16700Schasinglulu /* There are up to 14 IO unit which need address decode in Armada-3700 */ 31*91f16700Schasinglulu #define IO_UNIT_NUM_MAX (14) 32*91f16700Schasinglulu 33*91f16700Schasinglulu #define MVEBU_MAX_ADDRSS_4GB (0x100000000ULL) 34*91f16700Schasinglulu 35*91f16700Schasinglulu 36*91f16700Schasinglulu static void set_io_addr_dec_win(int win_id, uintptr_t base_addr, 37*91f16700Schasinglulu uintptr_t win_size, 38*91f16700Schasinglulu struct dec_win_config *dec_win) 39*91f16700Schasinglulu { 40*91f16700Schasinglulu uint32_t ctrl = 0; 41*91f16700Schasinglulu uint32_t base = 0; 42*91f16700Schasinglulu 43*91f16700Schasinglulu /* set size */ 44*91f16700Schasinglulu ctrl = ((win_size / MVEBU_WIN_BASE_SIZE_ALIGNMENT) - 1) << 45*91f16700Schasinglulu MVEBU_DEC_WIN_CTRL_SIZE_OFF; 46*91f16700Schasinglulu /* set attr according to IO decode window */ 47*91f16700Schasinglulu ctrl |= dec_win->win_attr << MVEBU_DEC_WIN_CTRL_ATTR_OFF; 48*91f16700Schasinglulu /* set target */ 49*91f16700Schasinglulu ctrl |= DRAM_CPU_DEC_TARGET_NUM << MVEBU_DEC_WIN_CTRL_TARGET_OFF; 50*91f16700Schasinglulu /* set base */ 51*91f16700Schasinglulu base = (base_addr / MVEBU_WIN_BASE_SIZE_ALIGNMENT) << 52*91f16700Schasinglulu MVEBU_DEC_WIN_BASE_OFF; 53*91f16700Schasinglulu 54*91f16700Schasinglulu /* set base address*/ 55*91f16700Schasinglulu mmio_write_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base, 56*91f16700Schasinglulu win_id, dec_win->win_offset), 57*91f16700Schasinglulu base); 58*91f16700Schasinglulu /* set remap window, some unit does not have remap window */ 59*91f16700Schasinglulu if (win_id < dec_win->max_remap) 60*91f16700Schasinglulu mmio_write_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base, 61*91f16700Schasinglulu win_id, dec_win->win_offset), base); 62*91f16700Schasinglulu /* set control register */ 63*91f16700Schasinglulu mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, 64*91f16700Schasinglulu win_id, dec_win->win_offset), ctrl); 65*91f16700Schasinglulu /* enable the address decode window at last to make it effective */ 66*91f16700Schasinglulu ctrl |= MVEBU_DEC_WIN_ENABLE << MVEBU_DEC_WIN_CTRL_EN_OFF; 67*91f16700Schasinglulu mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, 68*91f16700Schasinglulu win_id, dec_win->win_offset), ctrl); 69*91f16700Schasinglulu 70*91f16700Schasinglulu INFO("set_io_addr_dec %d result: ctrl(0x%x) base(0x%x) remap(0x%x)\n", 71*91f16700Schasinglulu win_id, mmio_read_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, 72*91f16700Schasinglulu win_id, dec_win->win_offset)), 73*91f16700Schasinglulu mmio_read_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base, 74*91f16700Schasinglulu win_id, dec_win->win_offset)), 75*91f16700Schasinglulu (win_id < dec_win->max_remap) ? 76*91f16700Schasinglulu mmio_read_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base, 77*91f16700Schasinglulu win_id, dec_win->win_offset)) : 0); 78*91f16700Schasinglulu } 79*91f16700Schasinglulu 80*91f16700Schasinglulu /* Set io decode window */ 81*91f16700Schasinglulu static int set_io_addr_dec(struct dram_win_map *win_map, 82*91f16700Schasinglulu struct dec_win_config *dec_win) 83*91f16700Schasinglulu { 84*91f16700Schasinglulu struct dram_win *win; 85*91f16700Schasinglulu int id; 86*91f16700Schasinglulu 87*91f16700Schasinglulu /* disable all windows first */ 88*91f16700Schasinglulu for (id = 0; id < dec_win->max_dram_win; id++) 89*91f16700Schasinglulu mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, id, 90*91f16700Schasinglulu dec_win->win_offset), 0); 91*91f16700Schasinglulu 92*91f16700Schasinglulu /* configure IO decode windows for DRAM, inheritate DRAM size, 93*91f16700Schasinglulu * base and target from CPU-DRAM decode window and others 94*91f16700Schasinglulu * from hard coded IO decode window settings array. 95*91f16700Schasinglulu */ 96*91f16700Schasinglulu if (win_map->dram_win_num > dec_win->max_dram_win) { 97*91f16700Schasinglulu /* 98*91f16700Schasinglulu * If cpu dram windows number exceeds the io decode windows 99*91f16700Schasinglulu * max number, then fill the first io decode window 100*91f16700Schasinglulu * with base(0) and size(4GB). 101*91f16700Schasinglulu */ 102*91f16700Schasinglulu set_io_addr_dec_win(0, 0, MVEBU_MAX_ADDRSS_4GB, dec_win); 103*91f16700Schasinglulu 104*91f16700Schasinglulu return 0; 105*91f16700Schasinglulu } 106*91f16700Schasinglulu 107*91f16700Schasinglulu for (id = 0; id < win_map->dram_win_num; id++, win++) { 108*91f16700Schasinglulu win = &win_map->dram_windows[id]; 109*91f16700Schasinglulu set_io_addr_dec_win(id, win->base_addr, win->win_size, dec_win); 110*91f16700Schasinglulu } 111*91f16700Schasinglulu 112*91f16700Schasinglulu return 0; 113*91f16700Schasinglulu } 114*91f16700Schasinglulu 115*91f16700Schasinglulu /* 116*91f16700Schasinglulu * init_io_addr_dec 117*91f16700Schasinglulu * 118*91f16700Schasinglulu * This function initializes io address decoder windows by 119*91f16700Schasinglulu * cpu dram window mapping information 120*91f16700Schasinglulu * 121*91f16700Schasinglulu * @input: N/A 122*91f16700Schasinglulu * - dram_wins_map: cpu dram windows mapping 123*91f16700Schasinglulu * - io_dec_config: io address decoder windows configuration 124*91f16700Schasinglulu * - io_unit_num: io address decoder unit number 125*91f16700Schasinglulu * @output: N/A 126*91f16700Schasinglulu * 127*91f16700Schasinglulu * @return: 0 on success and others on failure 128*91f16700Schasinglulu */ 129*91f16700Schasinglulu int init_io_addr_dec(struct dram_win_map *dram_wins_map, 130*91f16700Schasinglulu struct dec_win_config *io_dec_config, uint32_t io_unit_num) 131*91f16700Schasinglulu { 132*91f16700Schasinglulu int32_t index; 133*91f16700Schasinglulu struct dec_win_config *io_dec_win; 134*91f16700Schasinglulu int32_t ret; 135*91f16700Schasinglulu 136*91f16700Schasinglulu INFO("Initializing IO address decode windows\n"); 137*91f16700Schasinglulu 138*91f16700Schasinglulu if (io_dec_config == NULL || io_unit_num == 0) { 139*91f16700Schasinglulu ERROR("No IO address decoder windows configurations!\n"); 140*91f16700Schasinglulu return -1; 141*91f16700Schasinglulu } 142*91f16700Schasinglulu 143*91f16700Schasinglulu if (io_unit_num > IO_UNIT_NUM_MAX) { 144*91f16700Schasinglulu ERROR("IO address decoder windows number %d is over max %d\n", 145*91f16700Schasinglulu io_unit_num, IO_UNIT_NUM_MAX); 146*91f16700Schasinglulu return -1; 147*91f16700Schasinglulu } 148*91f16700Schasinglulu 149*91f16700Schasinglulu if (dram_wins_map == NULL) { 150*91f16700Schasinglulu ERROR("No cpu dram decoder windows map!\n"); 151*91f16700Schasinglulu return -1; 152*91f16700Schasinglulu } 153*91f16700Schasinglulu 154*91f16700Schasinglulu for (index = 0; index < dram_wins_map->dram_win_num; index++) 155*91f16700Schasinglulu INFO("DRAM mapping %d base(0x%lx) size(0x%lx)\n", 156*91f16700Schasinglulu index, dram_wins_map->dram_windows[index].base_addr, 157*91f16700Schasinglulu dram_wins_map->dram_windows[index].win_size); 158*91f16700Schasinglulu 159*91f16700Schasinglulu /* Set address decode window for each IO */ 160*91f16700Schasinglulu for (index = 0; index < io_unit_num; index++) { 161*91f16700Schasinglulu io_dec_win = io_dec_config + index; 162*91f16700Schasinglulu ret = set_io_addr_dec(dram_wins_map, io_dec_win); 163*91f16700Schasinglulu if (ret) { 164*91f16700Schasinglulu ERROR("Failed to set IO address decode\n"); 165*91f16700Schasinglulu return -1; 166*91f16700Schasinglulu } 167*91f16700Schasinglulu INFO("Set IO decode window successfully, base(0x%x)" 168*91f16700Schasinglulu " win_attr(%x) max_dram_win(%d) max_remap(%d)" 169*91f16700Schasinglulu " win_offset(%d)\n", io_dec_win->dec_reg_base, 170*91f16700Schasinglulu io_dec_win->win_attr, io_dec_win->max_dram_win, 171*91f16700Schasinglulu io_dec_win->max_remap, io_dec_win->win_offset); 172*91f16700Schasinglulu } 173*91f16700Schasinglulu 174*91f16700Schasinglulu return 0; 175*91f16700Schasinglulu } 176