0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifndef __CVMX_H__
0029 #define __CVMX_H__
0030
0031 #include <linux/kernel.h>
0032 #include <linux/string.h>
0033 #include <linux/delay.h>
0034
0035 enum cvmx_mips_space {
0036 CVMX_MIPS_SPACE_XKSEG = 3LL,
0037 CVMX_MIPS_SPACE_XKPHYS = 2LL,
0038 CVMX_MIPS_SPACE_XSSEG = 1LL,
0039 CVMX_MIPS_SPACE_XUSEG = 0LL
0040 };
0041
0042
0043 #define CVMX_MIPS32_SPACE_KSEG0 1l
0044 #define CVMX_ADD_SEG32(segment, add) \
0045 (((int32_t)segment << 31) | (int32_t)(add))
0046
0047 #define CVMX_IO_SEG CVMX_MIPS_SPACE_XKPHYS
0048
0049
0050 #define CVMX_ADD_SEG(segment, add) \
0051 ((((uint64_t)segment) << 62) | (add))
0052 #ifndef CVMX_ADD_IO_SEG
0053 #define CVMX_ADD_IO_SEG(add) CVMX_ADD_SEG(CVMX_IO_SEG, (add))
0054 #endif
0055
0056 #include <asm/octeon/cvmx-asm.h>
0057 #include <asm/octeon/cvmx-packet.h>
0058 #include <asm/octeon/cvmx-sysinfo.h>
0059
0060 #include <asm/octeon/cvmx-ciu-defs.h>
0061 #include <asm/octeon/cvmx-ciu3-defs.h>
0062 #include <asm/octeon/cvmx-gpio-defs.h>
0063 #include <asm/octeon/cvmx-iob-defs.h>
0064 #include <asm/octeon/cvmx-ipd-defs.h>
0065 #include <asm/octeon/cvmx-l2c-defs.h>
0066 #include <asm/octeon/cvmx-l2d-defs.h>
0067 #include <asm/octeon/cvmx-l2t-defs.h>
0068 #include <asm/octeon/cvmx-led-defs.h>
0069 #include <asm/octeon/cvmx-mio-defs.h>
0070 #include <asm/octeon/cvmx-pow-defs.h>
0071
0072 #include <asm/octeon/cvmx-bootinfo.h>
0073 #include <asm/octeon/cvmx-bootmem.h>
0074 #include <asm/octeon/cvmx-l2c.h>
0075
0076 #ifndef CVMX_ENABLE_DEBUG_PRINTS
0077 #define CVMX_ENABLE_DEBUG_PRINTS 1
0078 #endif
0079
0080 #if CVMX_ENABLE_DEBUG_PRINTS
0081 #define cvmx_dprintf printk
0082 #else
0083 #define cvmx_dprintf(...) {}
0084 #endif
0085
0086 #define CVMX_MAX_CORES (16)
0087 #define CVMX_CACHE_LINE_SIZE (128)
0088 #define CVMX_CACHE_LINE_MASK (CVMX_CACHE_LINE_SIZE - 1)
0089 #define CVMX_CACHE_LINE_ALIGNED __attribute__ ((aligned(CVMX_CACHE_LINE_SIZE)))
0090 #define CAST64(v) ((long long)(long)(v))
0091 #define CASTPTR(type, v) ((type *)(long)(v))
0092
0093
0094
0095
0096
0097 static inline uint32_t cvmx_get_proc_id(void) __attribute__ ((pure));
0098 static inline uint32_t cvmx_get_proc_id(void)
0099 {
0100 uint32_t id;
0101 asm("mfc0 %0, $15,0" : "=r"(id));
0102 return id;
0103 }
0104
0105
0106 #define CVMX_TMP_STR(x) CVMX_TMP_STR2(x)
0107 #define CVMX_TMP_STR2(x) #x
0108
0109
0110
0111
0112
0113
0114 static inline uint64_t cvmx_build_mask(uint64_t bits)
0115 {
0116 return ~((~0x0ull) << bits);
0117 }
0118
0119
0120
0121
0122
0123
0124
0125
0126 static inline uint64_t cvmx_build_io_address(uint64_t major_did,
0127 uint64_t sub_did)
0128 {
0129 return (0x1ull << 48) | (major_did << 43) | (sub_did << 40);
0130 }
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 static inline uint64_t cvmx_build_bits(uint64_t high_bit,
0150 uint64_t low_bit, uint64_t value)
0151 {
0152 return (value & cvmx_build_mask(high_bit - low_bit + 1)) << low_bit;
0153 }
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163 static inline uint64_t cvmx_ptr_to_phys(void *ptr)
0164 {
0165 if (sizeof(void *) == 8) {
0166
0167
0168
0169
0170
0171
0172
0173
0174 if ((CAST64(ptr) >> 62) == 3)
0175 return CAST64(ptr) & cvmx_build_mask(30);
0176 else
0177 return CAST64(ptr) & cvmx_build_mask(40);
0178 } else {
0179 return (long)(ptr) & 0x1fffffff;
0180 }
0181 }
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 static inline void *cvmx_phys_to_ptr(uint64_t physical_address)
0192 {
0193 if (sizeof(void *) == 8) {
0194
0195 return CASTPTR(void,
0196 CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
0197 physical_address));
0198 } else {
0199 return CASTPTR(void,
0200 CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0,
0201 physical_address));
0202 }
0203 }
0204
0205
0206
0207
0208
0209
0210
0211
0212 #define CVMX_BUILD_WRITE64(TYPE, ST) \
0213 static inline void cvmx_write64_##TYPE(uint64_t addr, TYPE##_t val) \
0214 { \
0215 *CASTPTR(volatile TYPE##_t, addr) = val; \
0216 }
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 #define CVMX_BUILD_READ64(TYPE, LT) \
0227 static inline TYPE##_t cvmx_read64_##TYPE(uint64_t addr) \
0228 { \
0229 return *CASTPTR(volatile TYPE##_t, addr); \
0230 }
0231
0232
0233
0234
0235
0236
0237
0238
0239 CVMX_BUILD_WRITE64(int64, "sd");
0240 CVMX_BUILD_WRITE64(int32, "sw");
0241 CVMX_BUILD_WRITE64(int16, "sh");
0242 CVMX_BUILD_WRITE64(int8, "sb");
0243 CVMX_BUILD_WRITE64(uint64, "sd");
0244 CVMX_BUILD_WRITE64(uint32, "sw");
0245 CVMX_BUILD_WRITE64(uint16, "sh");
0246 CVMX_BUILD_WRITE64(uint8, "sb");
0247 #define cvmx_write64 cvmx_write64_uint64
0248
0249
0250
0251
0252
0253
0254
0255 CVMX_BUILD_READ64(int64, "ld");
0256 CVMX_BUILD_READ64(int32, "lw");
0257 CVMX_BUILD_READ64(int16, "lh");
0258 CVMX_BUILD_READ64(int8, "lb");
0259 CVMX_BUILD_READ64(uint64, "ld");
0260 CVMX_BUILD_READ64(uint32, "lw");
0261 CVMX_BUILD_READ64(uint16, "lhu");
0262 CVMX_BUILD_READ64(uint8, "lbu");
0263 #define cvmx_read64 cvmx_read64_uint64
0264
0265
0266 static inline void cvmx_write_csr(uint64_t csr_addr, uint64_t val)
0267 {
0268 cvmx_write64(csr_addr, val);
0269
0270
0271
0272
0273
0274
0275
0276 if (((csr_addr >> 40) & 0x7ffff) == (0x118))
0277 cvmx_read64(CVMX_MIO_BOOT_BIST_STAT);
0278 }
0279
0280 static inline void cvmx_writeq_csr(void __iomem *csr_addr, uint64_t val)
0281 {
0282 cvmx_write_csr((__force uint64_t)csr_addr, val);
0283 }
0284
0285 static inline void cvmx_write_io(uint64_t io_addr, uint64_t val)
0286 {
0287 cvmx_write64(io_addr, val);
0288
0289 }
0290
0291 static inline uint64_t cvmx_read_csr(uint64_t csr_addr)
0292 {
0293 uint64_t val = cvmx_read64(csr_addr);
0294 return val;
0295 }
0296
0297 static inline uint64_t cvmx_readq_csr(void __iomem *csr_addr)
0298 {
0299 return cvmx_read_csr((__force uint64_t) csr_addr);
0300 }
0301
0302 static inline void cvmx_send_single(uint64_t data)
0303 {
0304 const uint64_t CVMX_IOBDMA_SENDSINGLE = 0xffffffffffffa200ull;
0305 cvmx_write64(CVMX_IOBDMA_SENDSINGLE, data);
0306 }
0307
0308 static inline void cvmx_read_csr_async(uint64_t scraddr, uint64_t csr_addr)
0309 {
0310 union {
0311 uint64_t u64;
0312 struct {
0313 uint64_t scraddr:8;
0314 uint64_t len:8;
0315 uint64_t addr:48;
0316 } s;
0317 } addr;
0318 addr.u64 = csr_addr;
0319 addr.s.scraddr = scraddr >> 3;
0320 addr.s.len = 1;
0321 cvmx_send_single(addr.u64);
0322 }
0323
0324
0325 static inline int cvmx_octeon_is_pass1(void)
0326 {
0327 #if OCTEON_IS_COMMON_BINARY()
0328 return 0;
0329 #else
0330
0331 #if OCTEON_IS_MODEL(OCTEON_CN38XX)
0332 return cvmx_get_proc_id() == OCTEON_CN38XX_PASS1;
0333 #else
0334 return 0;
0335 #endif
0336 #endif
0337 }
0338
0339 static inline unsigned int cvmx_get_core_num(void)
0340 {
0341 unsigned int core_num;
0342 CVMX_RDHWRNV(core_num, 0);
0343 return core_num;
0344 }
0345
0346
0347 #define CVMX_NODE_NO_SHIFT 7
0348 #define CVMX_NODE_MASK 0x3
0349 static inline unsigned int cvmx_get_node_num(void)
0350 {
0351 unsigned int core_num = cvmx_get_core_num();
0352
0353 return (core_num >> CVMX_NODE_NO_SHIFT) & CVMX_NODE_MASK;
0354 }
0355
0356 static inline unsigned int cvmx_get_local_core_num(void)
0357 {
0358 return cvmx_get_core_num() & ((1 << CVMX_NODE_NO_SHIFT) - 1);
0359 }
0360
0361 #define CVMX_NODE_BITS (2)
0362 #define CVMX_MAX_NODES (1 << CVMX_NODE_BITS)
0363 #define CVMX_NODE_IO_SHIFT (36)
0364 #define CVMX_NODE_MEM_SHIFT (40)
0365 #define CVMX_NODE_IO_MASK ((uint64_t)CVMX_NODE_MASK << CVMX_NODE_IO_SHIFT)
0366
0367 static inline void cvmx_write_csr_node(uint64_t node, uint64_t csr_addr,
0368 uint64_t val)
0369 {
0370 uint64_t composite_csr_addr, node_addr;
0371
0372 node_addr = (node & CVMX_NODE_MASK) << CVMX_NODE_IO_SHIFT;
0373 composite_csr_addr = (csr_addr & ~CVMX_NODE_IO_MASK) | node_addr;
0374
0375 cvmx_write64_uint64(composite_csr_addr, val);
0376 if (((csr_addr >> 40) & 0x7ffff) == (0x118))
0377 cvmx_read64_uint64(CVMX_MIO_BOOT_BIST_STAT | node_addr);
0378 }
0379
0380 static inline uint64_t cvmx_read_csr_node(uint64_t node, uint64_t csr_addr)
0381 {
0382 uint64_t node_addr;
0383
0384 node_addr = (csr_addr & ~CVMX_NODE_IO_MASK) |
0385 (node & CVMX_NODE_MASK) << CVMX_NODE_IO_SHIFT;
0386 return cvmx_read_csr(node_addr);
0387 }
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397 static inline uint32_t cvmx_pop(uint32_t val)
0398 {
0399 uint32_t pop;
0400 CVMX_POP(pop, val);
0401 return pop;
0402 }
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412 static inline int cvmx_dpop(uint64_t val)
0413 {
0414 int pop;
0415 CVMX_DPOP(pop, val);
0416 return pop;
0417 }
0418
0419
0420
0421
0422
0423
0424
0425 static inline uint64_t cvmx_get_cycle(void)
0426 {
0427 uint64_t cycle;
0428 CVMX_RDHWR(cycle, 31);
0429 return cycle;
0430 }
0431
0432
0433
0434
0435
0436
0437
0438
0439 static inline uint64_t cvmx_get_cycle_global(void)
0440 {
0441 if (cvmx_octeon_is_pass1())
0442 return 0;
0443 else
0444 return cvmx_read64(CVMX_IPD_CLK_COUNT);
0445 }
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456 #define CVMX_WAIT_FOR_FIELD64(address, type, field, op, value, timeout_usec)\
0457 ( \
0458 { \
0459 int result; \
0460 do { \
0461 uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec * \
0462 cvmx_sysinfo_get()->cpu_clock_hz / 1000000; \
0463 type c; \
0464 while (1) { \
0465 c.u64 = cvmx_read_csr(address); \
0466 if ((c.s.field) op(value)) { \
0467 result = 0; \
0468 break; \
0469 } else if (cvmx_get_cycle() > done) { \
0470 result = -1; \
0471 break; \
0472 } else \
0473 __delay(100); \
0474 } \
0475 } while (0); \
0476 result; \
0477 })
0478
0479
0480
0481
0482 static inline uint32_t cvmx_octeon_num_cores(void)
0483 {
0484 u64 ciu_fuse_reg;
0485 u64 ciu_fuse;
0486
0487 if (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX))
0488 ciu_fuse_reg = CVMX_CIU3_FUSE;
0489 else
0490 ciu_fuse_reg = CVMX_CIU_FUSE;
0491 ciu_fuse = cvmx_read_csr(ciu_fuse_reg);
0492 return cvmx_dpop(ciu_fuse);
0493 }
0494
0495 #endif