cvmx-llm.h revision 210284
1/***********************license start***************
2 *  Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
3 *  reserved.
4 *
5 *
6 *  Redistribution and use in source and binary forms, with or without
7 *  modification, are permitted provided that the following conditions are
8 *  met:
9 *
10 *      * Redistributions of source code must retain the above copyright
11 *        notice, this list of conditions and the following disclaimer.
12 *
13 *      * Redistributions in binary form must reproduce the above
14 *        copyright notice, this list of conditions and the following
15 *        disclaimer in the documentation and/or other materials provided
16 *        with the distribution.
17 *
18 *      * Neither the name of Cavium Networks nor the names of
19 *        its contributors may be used to endorse or promote products
20 *        derived from this software without specific prior written
21 *        permission.
22 *
23 *  TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
24 *  AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
25 *  OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
26 *  RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
27 *  REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
28 *  DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
29 *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
30 *  PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
31 *  POSSESSION OR CORRESPONDENCE TO DESCRIPTION.  THE ENTIRE RISK ARISING OUT
32 *  OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
33 *
34 *
35 *  For any questions regarding licensing please contact marketing@caviumnetworks.com
36 *
37 ***********************license end**************************************/
38
39
40
41
42
43
44/**
45 * @file
46 *
47 * interface to the low latency DRAM
48 *
49 * <hr>$Revision: 41586 $<hr>
50 *
51 */
52
53#ifndef __CVMX_LLM_H__
54#define __CVMX_LLM_H__
55
56#ifdef	__cplusplus
57extern "C" {
58#endif
59
60#define ENABLE_DEPRECATED   /* Set to enable the old 18/36 bit names */
61
62typedef enum
63{
64    CVMX_LLM_REPLICATION_NONE = 0,
65    CVMX_LLM_REPLICATION_2X = 1, // on both interfaces, or 2x if only one interface
66    CVMX_LLM_REPLICATION_4X = 2, // both interfaces, 2x, or 4x if only one interface
67    CVMX_LLM_REPLICATION_8X = 3, // both interfaces, 4x,  or 8x if only one interface
68} cvmx_llm_replication_t;
69
70/**
71 * This structure defines the address used to the low-latency memory.
72 * This address format is used for both loads and stores.
73 */
74typedef union
75{
76    uint64_t u64;
77    struct
78    {
79        uint64_t                mbz     :30;
80        cvmx_llm_replication_t  repl    : 2;
81        uint64_t                address :32; // address<1:0> mbz, address<31:30> mbz
82    } s;
83} cvmx_llm_address_t;
84
85/**
86 * This structure defines the data format in the low-latency memory
87 */
88typedef union
89{
90    uint64_t u64;
91
92    /**
93     * this format defines the format returned on a load
94     *   a load returns the 32/36-bits in memory, plus xxor = even_parity(dat<35:0>)
95     *   typically, dat<35> = parity(dat<34:0>), so the xor bit directly indicates parity error
96     *   Note that the data field size is 36 bits on the 36XX/38XX, and 32 bits on the 31XX
97     */
98    struct
99    {
100        uint64_t                       mbz1  :27;
101        uint64_t                       xxor  : 1;
102        uint64_t                       mbz   : 4;
103        uint64_t                       dat   :32;
104    } cn31xx;
105
106    struct
107    {
108        uint64_t                       mbz   :27;
109        uint64_t                       xxor  : 1;
110        uint64_t                       dat   :36;
111    } s;
112
113    /**
114     *  This format defines what should be used if parity is desired.  Hardware returns
115     *  the XOR of all the bits in the 36/32 bit data word, so for parity software must use
116     * one of the data field bits as a parity bit.
117     */
118    struct cn31xx_par_struct
119    {
120        uint64_t                       mbz   :32;
121        uint64_t                       par   : 1;
122        uint64_t                       dat   :31;
123    } cn31xx_par;
124    struct cn38xx_par_struct
125    {
126        uint64_t                       mbz   :28;
127        uint64_t                       par   : 1;
128        uint64_t                       dat   :35;
129    } cn38xx_par;
130#if !OCTEON_IS_COMMON_BINARY()
131#if CVMX_COMPILED_FOR(OCTEON_CN31XX)
132    struct cn31xx_par_struct spar;
133#else
134    struct cn38xx_par_struct spar;
135#endif
136#endif
137} cvmx_llm_data_t;
138
139#define CVMX_LLM_NARROW_DATA_WIDTH  ((CVMX_COMPILED_FOR(OCTEON_CN31XX)) ? 32 : 36)
140
141/**
142 * Calculate the parity value of a number
143 *
144 * @param value
145 * @return parity value
146 */
147static inline uint64_t cvmx_llm_parity(uint64_t value)
148{
149    uint64_t result;
150    CVMX_DPOP(result, value);
151    return result;
152}
153
154
155/**
156 * Calculate the ECC needed for 36b LLM mode
157 *
158 * @param value
159 * @return  ECC value
160 */
161static inline int cvmx_llm_ecc(uint64_t value)
162{
163    /* FIXME: This needs a re-write */
164    static const uint32_t ecc_code_29[7] = {
165        0x08962595,
166        0x112a4aaa,
167        0x024c934f,
168        0x04711c73,
169        0x0781e07c,
170        0x1801ff80,
171        0x1ffe0000};
172    uint64_t pop0, pop1, pop2, pop3, pop4, pop5, pop6;
173
174    pop0 = ecc_code_29[0];
175    pop1 = ecc_code_29[1];
176    pop2 = ecc_code_29[2];
177    pop0 &= value;
178    pop3 = ecc_code_29[3];
179    CVMX_DPOP(pop0, pop0);
180    pop4 = ecc_code_29[4];
181    pop1 &= value;
182    CVMX_DPOP(pop1, pop1);
183    pop2 &= value;
184    pop5 = ecc_code_29[5];
185    CVMX_DPOP(pop2, pop2);
186    pop6 = ecc_code_29[6];
187    pop3 &= value;
188    CVMX_DPOP(pop3, pop3);
189    pop4 &= value;
190    CVMX_DPOP(pop4, pop4);
191    pop5 &= value;
192    CVMX_DPOP(pop5, pop5);
193    pop6 &= value;
194    CVMX_DPOP(pop6, pop6);
195
196    return((pop6&1)<<6) | ((pop5&1)<<5) | ((pop4&1)<<4) | ((pop3&1)<<3) | ((pop2&1)<<2) | ((pop1&1)<<1) | (pop0&1);
197}
198
199
200#ifdef ENABLE_DEPRECATED
201/* These macros are provided to provide compatibility with code that uses
202** the old names for the llm access functions.  The names were changed
203** when support for the 31XX llm was added, as the widths differ between Octeon Models.
204** The wide/narrow names are preferred, and should be used in all new code */
205#define cvmx_llm_write36 cvmx_llm_write_narrow
206#define cvmx_llm_read36  cvmx_llm_read_narrow
207#define cvmx_llm_write64 cvmx_llm_write_wide
208#define cvmx_llm_read64  cvmx_llm_read_wide
209#endif
210/**
211 * Write to LLM memory - 36 bit
212 *
213 * @param address Address in LLM to write. Consecutive writes increment the
214 *                address by 4. The replication mode is also encoded in this
215 *                address.
216 * @param value   Value to write to LLM. Only the low 36 bits will be used.
217 * @param set     Which of the two coprocessor 2 register sets to use for the
218 *                write. May be used to get two outstanding LLM access at once
219 *                per core. Range: 0-1
220 */
221static inline void cvmx_llm_write_narrow(cvmx_llm_address_t address, uint64_t value, int set)
222{
223    cvmx_llm_data_t data;
224    data.s.mbz = 0;
225
226    if (cvmx_octeon_is_pass1())
227        data.s.dat = ((value & 0x3ffff) << 18) | ((value >> 18) & 0x3ffff);
228    else
229        data.s.dat = value;
230
231    data.s.xxor = 0;
232
233    if (set)
234    {
235        CVMX_MT_LLM_DATA(1, data.u64);
236        CVMX_MT_LLM_WRITE_ADDR_INTERNAL(1, address.u64);
237    }
238    else
239    {
240        CVMX_MT_LLM_DATA(0, data.u64);
241        CVMX_MT_LLM_WRITE_ADDR_INTERNAL(0, address.u64);
242    }
243}
244
245
246/**
247 * Write to LLM memory - 64 bit
248 *
249 * @param address Address in LLM to write. Consecutive writes increment the
250 *                address by 8. The replication mode is also encoded in this
251 *                address.
252 * @param value   Value to write to LLM.
253 * @param set     Which of the two coprocessor 2 register sets to use for the
254 *                write. May be used to get two outstanding LLM access at once
255 *                per core. Range: 0-1
256 */
257static inline void cvmx_llm_write_wide(cvmx_llm_address_t address, uint64_t value, int set)
258{
259    if (cvmx_octeon_is_pass1())
260    {
261        cvmx_llm_write36(address, value & 0xfffffffffull, set);
262        address.s.address+=4;
263        cvmx_llm_write36(address, ((value>>36) & 0xfffffff) | (cvmx_llm_ecc(value) << 28), set);
264    }
265    else
266    {
267        if (set)
268        {
269            CVMX_MT_LLM_DATA(1, value);
270            CVMX_MT_LLM_WRITE64_ADDR_INTERNAL(1, address.u64);
271        }
272        else
273        {
274            CVMX_MT_LLM_DATA(0, value);
275            CVMX_MT_LLM_WRITE64_ADDR_INTERNAL(0, address.u64);
276        }
277    }
278}
279
280
281/**
282 * Read from LLM memory - 36 bit
283 *
284 * @param address Address in LLM to read. Consecutive reads increment the
285 *                address by 4. The replication mode is also encoded in this
286 *                address.
287 * @param set     Which of the two coprocessor 2 register sets to use for the
288 *                write. May be used to get two outstanding LLM access at once
289 *                per core. Range: 0-1
290 * @return The lower 36 bits contain the result of the read
291 */
292static inline cvmx_llm_data_t cvmx_llm_read_narrow(cvmx_llm_address_t address, int set)
293{
294    cvmx_llm_data_t value;
295    if (set)
296    {
297        CVMX_MT_LLM_READ_ADDR(1, address.u64);
298        CVMX_MF_LLM_DATA(1, value.u64);
299    }
300    else
301    {
302        CVMX_MT_LLM_READ_ADDR(0, address.u64);
303        CVMX_MF_LLM_DATA(0, value.u64);
304    }
305    return value;
306}
307
308
309/**
310 * Read from LLM memory - 64 bit
311 *
312 * @param address Address in LLM to read. Consecutive reads increment the
313 *                address by 8. The replication mode is also encoded in this
314 *                address.
315 * @param set     Which of the two coprocessor 2 register sets to use for the
316 *                write. May be used to get two outstanding LLM access at once
317 *                per core. Range: 0-1
318 * @return The result of the read
319 */
320static inline uint64_t cvmx_llm_read_wide(cvmx_llm_address_t address, int set)
321{
322    uint64_t value;
323    if (set)
324    {
325        CVMX_MT_LLM_READ64_ADDR(1, address);
326        CVMX_MF_LLM_DATA(1, value);
327    }
328    else
329    {
330        CVMX_MT_LLM_READ64_ADDR(0, address);
331        CVMX_MF_LLM_DATA(0, value);
332    }
333    return value;
334}
335
336
337#define RLD_INIT_DELAY  (1<<18)
338
339
340
341/* This structure describes the RLDRAM configuration for a board.  This structure
342** must be populated with the correct values and passed to the initialization function.
343*/
344typedef struct
345{
346    uint32_t cpu_hz;            /* CPU frequency in Hz */
347    char addr_rld0_fb_str [100];   /* String describing RLDRAM connections on rld 0 front (0) bunk*/
348    char addr_rld0_bb_str [100];   /* String describing RLDRAM connections on rld 0 back (1) bunk*/
349    char addr_rld1_fb_str [100];   /* String describing RLDRAM connections on rld 1 front (0) bunk*/
350    char addr_rld1_bb_str [100];   /* String describing RLDRAM connections on rld 1 back (1) bunk*/
351    uint8_t rld0_bunks;     /* Number of bunks on rld 0 (0 is disabled) */
352    uint8_t rld1_bunks;     /* Number of bunks on rld 1 (0 is disabled) */
353    uint16_t rld0_mbytes;   /* mbytes on rld 0 */
354    uint16_t rld1_mbytes;   /* mbytes on rld 1 */
355    uint16_t max_rld_clock_mhz;  /* Maximum RLD clock in MHz, only used for CN58XX */
356} llm_descriptor_t;
357
358/**
359 * Initialize LLM memory controller.  This must be done
360 * before the low latency memory can be used.
361 * This is simply a wrapper around cvmx_llm_initialize_desc(),
362 * and is deprecated.
363 *
364 * @return -1 on error
365 *         0 on success
366 */
367int cvmx_llm_initialize(void);
368
369
370/**
371 * Initialize LLM memory controller.  This must be done
372 * before the low latency memory can be used.
373 *
374 * @param llm_desc_ptr
375 *              Pointer to descriptor structure. If NULL
376 *              is passed, a default setting is used if available.
377 *
378 * @return -1 on error
379 *         Size of llm in bytes on success
380 */
381int cvmx_llm_initialize_desc(llm_descriptor_t *llm_desc_ptr);
382
383
384
385/**
386 * Gets the default llm descriptor for the board code is being run on.
387 *
388 * @param llm_desc_ptr
389 *               Pointer to descriptor structure to be filled in.  Contents are only
390 *               valid after successful completion.  Must not be NULL.
391 *
392 * @return -1 on error
393 *         0 on success
394 */
395int cvmx_llm_get_default_descriptor(llm_descriptor_t *llm_desc_ptr);
396
397#ifdef	__cplusplus
398}
399#endif
400
401#endif /*  __CVM_LLM_H__ */
402