2 * Copyright (C) 2016 - 2018 Marvell International Ltd.
4 * SPDX-License-Identifier: BSD-3-Clause
5 * https://spdx.org/licenses
8 /* IOW unit device driver for Marvell CP110 and CP115 SoCs */
10 #include <armada_common.h>
11 #include <arch_helpers.h>
16 #include <mvebu_def.h>
18 #if LOG_LEVEL >= LOG_LEVEL_INFO
19 #define DEBUG_ADDR_MAP
22 #define MVEBU_IOB_OFFSET (0x190000)
23 #define MVEBU_IOB_MAX_WINS 16
26 #define WIN_ENABLE_BIT (0x1)
27 /* Physical address of the base of the window = {AddrLow[19:0],20`h0} */
28 #define ADDRESS_SHIFT (20 - 4)
29 #define ADDRESS_MASK (0xFFFFFFF0)
30 #define IOB_WIN_ALIGNMENT (0x100000)
33 #define IOB_WIN_CR_OFFSET(win) (iob_base + 0x0 + (0x20 * win))
34 #define IOB_TARGET_ID_OFFSET (8)
35 #define IOB_TARGET_ID_MASK (0xF)
37 #define IOB_WIN_SCR_OFFSET(win) (iob_base + 0x4 + (0x20 * win))
38 #define IOB_WIN_ENA_CTRL_WRITE_SECURE (0x1)
39 #define IOB_WIN_ENA_CTRL_READ_SECURE (0x2)
40 #define IOB_WIN_ENA_WRITE_SECURE (0x4)
41 #define IOB_WIN_ENA_READ_SECURE (0x8)
43 #define IOB_WIN_ALR_OFFSET(win) (iob_base + 0x8 + (0x20 * win))
44 #define IOB_WIN_AHR_OFFSET(win) (iob_base + 0xC + (0x20 * win))
48 static void iob_win_check(struct addr_map_win
*win
, uint32_t win_num
)
50 /* check if address is aligned to the size */
51 if (IS_NOT_ALIGN(win
->base_addr
, IOB_WIN_ALIGNMENT
)) {
52 win
->base_addr
= ALIGN_UP(win
->base_addr
, IOB_WIN_ALIGNMENT
);
53 ERROR("Window %d: base address unaligned to 0x%x\n",
54 win_num
, IOB_WIN_ALIGNMENT
);
55 printf("Align up the base address to 0x%llx\n",
59 /* size parameter validity check */
60 if (IS_NOT_ALIGN(win
->win_size
, IOB_WIN_ALIGNMENT
)) {
61 win
->win_size
= ALIGN_UP(win
->win_size
, IOB_WIN_ALIGNMENT
);
62 ERROR("Window %d: window size unaligned to 0x%x\n", win_num
,
64 printf("Aligning size to 0x%llx\n", win
->win_size
);
68 static void iob_enable_win(struct addr_map_win
*win
, uint32_t win_id
)
74 end_addr
= (win
->base_addr
+ win
->win_size
- 1);
75 alr
= (uint32_t)((win
->base_addr
>> ADDRESS_SHIFT
) & ADDRESS_MASK
);
76 ahr
= (uint32_t)((end_addr
>> ADDRESS_SHIFT
) & ADDRESS_MASK
);
78 mmio_write_32(IOB_WIN_ALR_OFFSET(win_id
), alr
);
79 mmio_write_32(IOB_WIN_AHR_OFFSET(win_id
), ahr
);
81 iob_win_reg
= WIN_ENABLE_BIT
;
82 iob_win_reg
|= (win
->target_id
& IOB_TARGET_ID_MASK
)
83 << IOB_TARGET_ID_OFFSET
;
84 mmio_write_32(IOB_WIN_CR_OFFSET(win_id
), iob_win_reg
);
89 static void dump_iob(void)
91 uint32_t win_id
, win_cr
, alr
, ahr
;
94 char *iob_target_name
[IOB_MAX_TID
] = {
95 "CFG ", "MCI0 ", "PEX1 ", "PEX2 ",
96 "PEX0 ", "NAND ", "RUNIT", "MCI1 " };
98 /* Dump all IOB windows */
99 printf("bank id target start end\n");
100 printf("----------------------------------------------------\n");
101 for (win_id
= 0; win_id
< MVEBU_IOB_MAX_WINS
; win_id
++) {
102 win_cr
= mmio_read_32(IOB_WIN_CR_OFFSET(win_id
));
103 if (win_cr
& WIN_ENABLE_BIT
) {
104 target_id
= (win_cr
>> IOB_TARGET_ID_OFFSET
) &
106 alr
= mmio_read_32(IOB_WIN_ALR_OFFSET(win_id
));
107 start
= ((uint64_t)alr
<< ADDRESS_SHIFT
);
109 ahr
= mmio_read_32(IOB_WIN_AHR_OFFSET(win_id
));
110 end
= (((uint64_t)ahr
+ 0x10) << ADDRESS_SHIFT
);
112 /* Window #0 size is hardcoded to 16MB, as it's
113 * reserved for CP configuration space.
115 end
= start
+ (16 << 20);
117 printf("iob %02d %s 0x%016llx 0x%016llx\n",
118 win_id
, iob_target_name
[target_id
],
125 void iob_cfg_space_update(int ap_idx
, int cp_idx
, uintptr_t base
,
130 iob_base
= base
+ MVEBU_IOB_OFFSET
;
132 NOTICE("Change the base address of AP%d-CP%d to %lx\n",
133 ap_idx
, cp_idx
, new_base
);
134 mmio_write_32(IOB_WIN_ALR_OFFSET(0), new_base
>> ADDRESS_SHIFT
);
136 iob_base
= new_base
+ MVEBU_IOB_OFFSET
;
138 /* Make sure the address was configured by the CPU before
139 * any possible access to the CP.
146 int init_iob(uintptr_t base
)
148 struct addr_map_win
*win
;
149 uint32_t win_id
, win_reg
;
152 INFO("Initializing IOB Address decoding\n");
154 /* Get the base address of the address decoding MBUS */
155 iob_base
= base
+ MVEBU_IOB_OFFSET
;
157 /* Get the array of the windows and fill the map data */
158 marvell_get_iob_memory_map(&win
, &win_count
, base
);
159 if (win_count
<= 0) {
160 INFO("no windows configurations found\n");
162 } else if (win_count
> (MVEBU_IOB_MAX_WINS
- 1)) {
163 ERROR("IOB mem map array > than max available windows (%d)\n",
165 win_count
= MVEBU_IOB_MAX_WINS
;
168 /* disable all IOB windows, start from win_id = 1
169 * because can't disable internal register window
171 for (win_id
= 1; win_id
< MVEBU_IOB_MAX_WINS
; win_id
++) {
172 win_reg
= mmio_read_32(IOB_WIN_CR_OFFSET(win_id
));
173 win_reg
&= ~WIN_ENABLE_BIT
;
174 mmio_write_32(IOB_WIN_CR_OFFSET(win_id
), win_reg
);
176 win_reg
= ~IOB_WIN_ENA_CTRL_WRITE_SECURE
;
177 win_reg
&= ~IOB_WIN_ENA_CTRL_READ_SECURE
;
178 win_reg
&= ~IOB_WIN_ENA_WRITE_SECURE
;
179 win_reg
&= ~IOB_WIN_ENA_READ_SECURE
;
180 mmio_write_32(IOB_WIN_SCR_OFFSET(win_id
), win_reg
);
183 for (win_id
= 1; win_id
< win_count
+ 1; win_id
++, win
++) {
184 iob_win_check(win
, win_id
);
185 iob_enable_win(win
, win_id
);
188 #ifdef DEBUG_ADDR_MAP
192 INFO("Done IOB Address decoding Initializing\n");