blob: 22270f1d0258462c07658f0d284cdee0375e19c0 [file] [log] [blame]
Kumar Gala83d40df2008-01-16 01:13:58 -06001/*
Kumar Gala21608272010-03-30 23:06:53 -05002 * Copyright 2008-2010 Freescale Semiconductor, Inc.
Kumar Gala83d40df2008-01-16 01:13:58 -06003 *
4 * (C) Copyright 2000
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26#include <common.h>
27#include <asm/fsl_law.h>
28#include <asm/io.h>
29
Kumar Galaf0600542008-06-11 00:44:10 -050030DECLARE_GLOBAL_DATA_PTR;
31
Kumar Galaf0600542008-06-11 00:44:10 -050032/* number of LAWs in the hw implementation */
33#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
34 defined(CONFIG_MPC8560) || defined(CONFIG_MPC8555)
35#define FSL_HW_NUM_LAWS 8
36#elif defined(CONFIG_MPC8548) || defined(CONFIG_MPC8544) || \
Haiying Wang22b6dbc2009-03-27 17:02:44 -040037 defined(CONFIG_MPC8568) || defined(CONFIG_MPC8569) || \
Kumar Galaf0600542008-06-11 00:44:10 -050038 defined(CONFIG_MPC8641) || defined(CONFIG_MPC8610)
39#define FSL_HW_NUM_LAWS 10
Srikanth Srinivasan8d949af2009-01-21 17:17:33 -060040#elif defined(CONFIG_MPC8536) || defined(CONFIG_MPC8572) || \
Poonam Aggrwala713ba92009-08-20 18:57:45 +053041 defined(CONFIG_P1011) || defined(CONFIG_P1020) || \
Kumar Gala21608272010-03-30 23:06:53 -050042 defined(CONFIG_P1012) || defined(CONFIG_P1021) || \
43 defined(CONFIG_P1013) || defined(CONFIG_P1022) || \
Poonam Aggrwala713ba92009-08-20 18:57:45 +053044 defined(CONFIG_P2010) || defined(CONFIG_P2020)
Kumar Galaf0600542008-06-11 00:44:10 -050045#define FSL_HW_NUM_LAWS 12
Kumar Gala19dbcc92009-10-21 13:32:58 -050046#elif defined(CONFIG_PPC_P4080) || defined(CONFIG_PPC_P5020)
Kumar Gala7e4259b2009-03-19 02:39:17 -050047#define FSL_HW_NUM_LAWS 32
Kumar Galaf0600542008-06-11 00:44:10 -050048#else
49#error FSL_HW_NUM_LAWS not defined for this platform
50#endif
Kumar Gala83d40df2008-01-16 01:13:58 -060051
Kumar Gala418ec852009-03-19 02:32:23 -050052#ifdef CONFIG_FSL_CORENET
Becky Brucee71755f2010-06-17 11:37:23 -050053#define LAW_BASE (CONFIG_SYS_FSL_CORENET_CCM_ADDR)
54#define LAWAR_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawar)
55#define LAWBARH_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarh)
56#define LAWBARL_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarl)
57#define LAWBAR_SHIFT 0
58#else
59#define LAW_BASE (CONFIG_SYS_IMMR + 0xc08)
60#define LAWAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x + 2)
61#define LAWBAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x)
62#define LAWBAR_SHIFT 12
63#endif
64
65
66static inline phys_addr_t get_law_base_addr(int idx)
67{
68#ifdef CONFIG_FSL_CORENET
69 return (phys_addr_t)
70 ((u64)in_be32(LAWBARH_ADDR(idx)) << 32) |
71 in_be32(LAWBARL_ADDR(idx));
72#else
73 return (phys_addr_t)in_be32(LAWBAR_ADDR(idx)) << LAWBAR_SHIFT;
74#endif
75}
76
77static inline void set_law_base_addr(int idx, phys_addr_t addr)
78{
79#ifdef CONFIG_FSL_CORENET
80 out_be32(LAWBARL_ADDR(idx), addr & 0xffffffff);
81 out_be32(LAWBARH_ADDR(idx), (u64)addr >> 32);
82#else
83 out_be32(LAWBAR_ADDR(idx), addr >> LAWBAR_SHIFT);
84#endif
85}
86
Kumar Gala418ec852009-03-19 02:32:23 -050087void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
88{
Kumar Gala418ec852009-03-19 02:32:23 -050089 gd->used_laws |= (1 << idx);
90
Becky Brucee71755f2010-06-17 11:37:23 -050091 out_be32(LAWAR_ADDR(idx), 0);
92 set_law_base_addr(idx, addr);
93 out_be32(LAWAR_ADDR(idx), LAW_EN | ((u32)id << 20) | (u32)sz);
Kumar Gala418ec852009-03-19 02:32:23 -050094
95 /* Read back so that we sync the writes */
Becky Brucee71755f2010-06-17 11:37:23 -050096 in_be32(LAWAR_ADDR(idx));
Kumar Gala418ec852009-03-19 02:32:23 -050097}
98
99void disable_law(u8 idx)
100{
Kumar Gala418ec852009-03-19 02:32:23 -0500101 gd->used_laws &= ~(1 << idx);
102
Becky Brucee71755f2010-06-17 11:37:23 -0500103 out_be32(LAWAR_ADDR(idx), 0);
104 set_law_base_addr(idx, 0);
Kumar Gala418ec852009-03-19 02:32:23 -0500105
106 /* Read back so that we sync the writes */
Becky Brucee71755f2010-06-17 11:37:23 -0500107 in_be32(LAWAR_ADDR(idx));
Kumar Gala418ec852009-03-19 02:32:23 -0500108
109 return;
110}
111
Kumar Gala24b17d82009-09-30 08:39:44 -0500112#ifndef CONFIG_NAND_SPL
Kumar Gala418ec852009-03-19 02:32:23 -0500113static int get_law_entry(u8 i, struct law_entry *e)
114{
Kumar Gala418ec852009-03-19 02:32:23 -0500115 u32 lawar;
116
Becky Brucee71755f2010-06-17 11:37:23 -0500117 lawar = in_be32(LAWAR_ADDR(i));
Kumar Gala418ec852009-03-19 02:32:23 -0500118
119 if (!(lawar & LAW_EN))
120 return 0;
121
Becky Brucee71755f2010-06-17 11:37:23 -0500122 e->addr = get_law_base_addr(i);
Kumar Gala418ec852009-03-19 02:32:23 -0500123 e->size = lawar & 0x3f;
124 e->trgt_id = (lawar >> 20) & 0xff;
125
126 return 1;
127}
Kumar Gala24b17d82009-09-30 08:39:44 -0500128#endif
Kumar Gala418ec852009-03-19 02:32:23 -0500129
Kumar Galaf0600542008-06-11 00:44:10 -0500130int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
131{
132 u32 idx = ffz(gd->used_laws);
133
134 if (idx >= FSL_HW_NUM_LAWS)
135 return -1;
136
137 set_law(idx, addr, sz, id);
138
139 return idx;
140}
141
Mingkai Hu7da53352009-09-11 14:19:10 +0800142#ifndef CONFIG_NAND_SPL
Kumar Galaba04f702008-06-10 16:16:02 -0500143int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
144{
145 u32 idx;
146
147 /* we have no LAWs free */
148 if (gd->used_laws == -1)
149 return -1;
150
151 /* grab the last free law */
152 idx = __ilog2(~(gd->used_laws));
153
154 if (idx >= FSL_HW_NUM_LAWS)
155 return -1;
156
157 set_law(idx, addr, sz, id);
158
159 return idx;
160}
161
Kumar Gala418ec852009-03-19 02:32:23 -0500162struct law_entry find_law(phys_addr_t addr)
Kumar Gala83d40df2008-01-16 01:13:58 -0600163{
Kumar Gala418ec852009-03-19 02:32:23 -0500164 struct law_entry entry;
165 int i;
Kumar Gala83d40df2008-01-16 01:13:58 -0600166
Kumar Gala418ec852009-03-19 02:32:23 -0500167 entry.index = -1;
168 entry.addr = 0;
169 entry.size = 0;
170 entry.trgt_id = 0;
Kumar Galaf0600542008-06-11 00:44:10 -0500171
Kumar Gala418ec852009-03-19 02:32:23 -0500172 for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
173 u64 upper;
Kumar Gala83d40df2008-01-16 01:13:58 -0600174
Kumar Gala418ec852009-03-19 02:32:23 -0500175 if (!get_law_entry(i, &entry))
176 continue;
177
178 upper = entry.addr + (2ull << entry.size);
179 if ((addr >= entry.addr) && (addr < upper)) {
180 entry.index = i;
181 break;
182 }
183 }
184
185 return entry;
Kumar Gala83d40df2008-01-16 01:13:58 -0600186}
187
Becky Bruceddcebcb2008-01-23 16:31:05 -0600188void print_laws(void)
189{
Becky Bruceddcebcb2008-01-23 16:31:05 -0600190 int i;
Becky Brucee71755f2010-06-17 11:37:23 -0500191 u32 lawar;
Becky Bruceddcebcb2008-01-23 16:31:05 -0600192
193 printf("\nLocal Access Window Configuration\n");
Becky Brucee71755f2010-06-17 11:37:23 -0500194 for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
195 lawar = in_be32(LAWAR_ADDR(i));
Becky Bruce11a3de42010-06-17 11:37:24 -0500196#ifdef CONFIG_FSL_CORENET
197 printf("LAWBARH%02d: 0x%08x LAWBARL%02d: 0x%08x",
198 i, in_be32(LAWBARH_ADDR(i)),
199 i, in_be32(LAWBARL_ADDR(i)));
200#else
Becky Brucee71755f2010-06-17 11:37:23 -0500201 printf("LAWBAR%02d: 0x%08x", i, in_be32(LAWBAR_ADDR(i)));
Becky Bruce11a3de42010-06-17 11:37:24 -0500202#endif
Becky Brucee71755f2010-06-17 11:37:23 -0500203 printf(" LAWAR0x%02d: 0x%08x\n", i, lawar);
204 printf("\t(EN: %d TGT: 0x%02x SIZE: ",
205 (lawar & LAW_EN) ? 1 : 0, (lawar >> 20) & 0xff);
206 print_size(lawar_size(lawar), ")\n");
Becky Bruceddcebcb2008-01-23 16:31:05 -0600207 }
208
209 return;
210}
211
Kumar Galaf784e322008-08-26 15:01:28 -0500212/* use up to 2 LAWs for DDR, used the last available LAWs */
213int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
214{
215 u64 start_align, law_sz;
216 int law_sz_enc;
217
218 if (start == 0)
219 start_align = 1ull << (LAW_SIZE_32G + 1);
220 else
221 start_align = 1ull << (ffs64(start) - 1);
222 law_sz = min(start_align, sz);
223 law_sz_enc = __ilog2_u64(law_sz) - 1;
224
225 if (set_last_law(start, law_sz_enc, id) < 0)
226 return -1;
227
Kumar Galae6a67892009-04-04 10:21:02 -0500228 /* recalculate size based on what was actually covered by the law */
229 law_sz = 1ull << __ilog2_u64(law_sz);
230
Kumar Galaf784e322008-08-26 15:01:28 -0500231 /* do we still have anything to map */
232 sz = sz - law_sz;
233 if (sz) {
234 start += law_sz;
235
236 start_align = 1ull << (ffs64(start) - 1);
237 law_sz = min(start_align, sz);
238 law_sz_enc = __ilog2_u64(law_sz) - 1;
239
240 if (set_last_law(start, law_sz_enc, id) < 0)
241 return -1;
242 } else {
243 return 0;
244 }
245
246 /* do we still have anything to map */
247 sz = sz - law_sz;
248 if (sz)
249 return 1;
250
251 return 0;
252}
Mingkai Hu7da53352009-09-11 14:19:10 +0800253#endif
Kumar Galaf784e322008-08-26 15:01:28 -0500254
Kumar Gala83d40df2008-01-16 01:13:58 -0600255void init_laws(void)
256{
257 int i;
Kumar Galaf0600542008-06-11 00:44:10 -0500258
Kumar Gala418ec852009-03-19 02:32:23 -0500259#if FSL_HW_NUM_LAWS < 32
Kumar Galaf0600542008-06-11 00:44:10 -0500260 gd->used_laws = ~((1 << FSL_HW_NUM_LAWS) - 1);
Kumar Gala418ec852009-03-19 02:32:23 -0500261#elif FSL_HW_NUM_LAWS == 32
262 gd->used_laws = 0;
263#else
264#error FSL_HW_NUM_LAWS can not be greater than 32 w/o code changes
265#endif
Kumar Gala83d40df2008-01-16 01:13:58 -0600266
267 for (i = 0; i < num_law_entries; i++) {
Kumar Galaf0600542008-06-11 00:44:10 -0500268 if (law_table[i].index == -1)
269 set_next_law(law_table[i].addr, law_table[i].size,
270 law_table[i].trgt_id);
271 else
272 set_law(law_table[i].index, law_table[i].addr,
273 law_table[i].size, law_table[i].trgt_id);
Kumar Gala83d40df2008-01-16 01:13:58 -0600274 }
275
276 return ;
277}