1/* 2 * Generic library functions for the microengines found on the Intel 3 * IXP2000 series of network processors. 4 * 5 * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org> 6 * Dedicated to Marija Kulikova. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as 10 * published by the Free Software Foundation; either version 2.1 of the 11 * License, or (at your option) any later version. 12 */ 13 14#include <linux/kernel.h> 15#include <linux/init.h> 16#include <linux/slab.h> 17#include <linux/module.h> 18#include <linux/string.h> 19#include <linux/io.h> 20#include <mach/hardware.h> 21#include <asm/hardware/uengine.h> 22 23#if defined(CONFIG_ARCH_IXP2000) 24#define IXP_UENGINE_CSR_VIRT_BASE IXP2000_UENGINE_CSR_VIRT_BASE 25#define IXP_PRODUCT_ID IXP2000_PRODUCT_ID 26#define IXP_MISC_CONTROL IXP2000_MISC_CONTROL 27#define IXP_RESET1 IXP2000_RESET1 28#else 29#if defined(CONFIG_ARCH_IXP23XX) 30#define IXP_UENGINE_CSR_VIRT_BASE IXP23XX_UENGINE_CSR_VIRT_BASE 31#define IXP_PRODUCT_ID IXP23XX_PRODUCT_ID 32#define IXP_MISC_CONTROL IXP23XX_MISC_CONTROL 33#define IXP_RESET1 IXP23XX_RESET1 34#else 35#error unknown platform 36#endif 37#endif 38 39#define USTORE_ADDRESS 0x000 40#define USTORE_DATA_LOWER 0x004 41#define USTORE_DATA_UPPER 0x008 42#define CTX_ENABLES 0x018 43#define CC_ENABLE 0x01c 44#define CSR_CTX_POINTER 0x020 45#define INDIRECT_CTX_STS 0x040 46#define ACTIVE_CTX_STS 0x044 47#define INDIRECT_CTX_SIG_EVENTS 0x048 48#define INDIRECT_CTX_WAKEUP_EVENTS 0x050 49#define NN_PUT 0x080 50#define NN_GET 0x084 51#define TIMESTAMP_LOW 0x0c0 52#define TIMESTAMP_HIGH 0x0c4 53#define T_INDEX_BYTE_INDEX 0x0f4 54#define LOCAL_CSR_STATUS 0x180 55 56u32 ixp2000_uengine_mask; 57 58static void *ixp2000_uengine_csr_area(int uengine) 59{ 60 return ((void *)IXP_UENGINE_CSR_VIRT_BASE) + (uengine << 10); 61} 62 63/* 64 * LOCAL_CSR_STATUS=1 after a read or write to a microengine's CSR 65 * space means that the microengine we tried to access was also trying 66 * to access its own CSR space on the same clock cycle as we did. When 67 * this happens, we lose the arbitration process by default, and the 68 * read or write we tried to do was not actually performed, so we try 69 * again until it succeeds. 70 */ 71u32 ixp2000_uengine_csr_read(int uengine, int offset) 72{ 73 void *uebase; 74 u32 *local_csr_status; 75 u32 *reg; 76 u32 value; 77 78 uebase = ixp2000_uengine_csr_area(uengine); 79 80 local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); 81 reg = (u32 *)(uebase + offset); 82 do { 83 value = ixp2000_reg_read(reg); 84 } while (ixp2000_reg_read(local_csr_status) & 1); 85 86 return value; 87} 88EXPORT_SYMBOL(ixp2000_uengine_csr_read); 89 90void ixp2000_uengine_csr_write(int uengine, int offset, u32 value) 91{ 92 void *uebase; 93 u32 *local_csr_status; 94 u32 *reg; 95 96 uebase = ixp2000_uengine_csr_area(uengine); 97 98 local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); 99 reg = (u32 *)(uebase + offset); 100 do { 101 ixp2000_reg_write(reg, value); 102 } while (ixp2000_reg_read(local_csr_status) & 1); 103} 104EXPORT_SYMBOL(ixp2000_uengine_csr_write); 105 106void ixp2000_uengine_reset(u32 uengine_mask) 107{ 108 u32 value; 109 110 value = ixp2000_reg_read(IXP_RESET1) & ~ixp2000_uengine_mask; 111 112 uengine_mask &= ixp2000_uengine_mask; 113 ixp2000_reg_wrb(IXP_RESET1, value | uengine_mask); 114 ixp2000_reg_wrb(IXP_RESET1, value); 115} 116EXPORT_SYMBOL(ixp2000_uengine_reset); 117 118void ixp2000_uengine_set_mode(int uengine, u32 mode) 119{ 120 /* 121 * CTL_STR_PAR_EN: unconditionally enable parity checking on 122 * control store. 123 */ 124 mode |= 0x10000000; 125 ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mode); 126 127 /* 128 * Enable updating of condition codes. 129 */ 130 ixp2000_uengine_csr_write(uengine, CC_ENABLE, 0x00002000); 131 132 /* 133 * Initialise other per-microengine registers. 134 */ 135 ixp2000_uengine_csr_write(uengine, NN_PUT, 0x00); 136 ixp2000_uengine_csr_write(uengine, NN_GET, 0x00); 137 ixp2000_uengine_csr_write(uengine, T_INDEX_BYTE_INDEX, 0); 138} 139EXPORT_SYMBOL(ixp2000_uengine_set_mode); 140 141static int make_even_parity(u32 x) 142{ 143 return hweight32(x) & 1; 144} 145 146static void ustore_write(int uengine, u64 insn) 147{ 148 /* 149 * Generate even parity for top and bottom 20 bits. 150 */ 151 insn |= (u64)make_even_parity((insn >> 20) & 0x000fffff) << 41; 152 insn |= (u64)make_even_parity(insn & 0x000fffff) << 40; 153 154 /* 155 * Write to microstore. The second write auto-increments 156 * the USTORE_ADDRESS index register. 157 */ 158 ixp2000_uengine_csr_write(uengine, USTORE_DATA_LOWER, (u32)insn); 159 ixp2000_uengine_csr_write(uengine, USTORE_DATA_UPPER, (u32)(insn >> 32)); 160} 161 162void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns) 163{ 164 int i; 165 166 /* 167 * Start writing to microstore at address 0. 168 */ 169 ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x80000000); 170 for (i = 0; i < insns; i++) { 171 u64 insn; 172 173 insn = (((u64)ucode[0]) << 32) | 174 (((u64)ucode[1]) << 24) | 175 (((u64)ucode[2]) << 16) | 176 (((u64)ucode[3]) << 8) | 177 ((u64)ucode[4]); 178 ucode += 5; 179 180 ustore_write(uengine, insn); 181 } 182 183 /* 184 * Pad with a few NOPs at the end (to avoid the microengine 185 * aborting as it prefetches beyond the last instruction), unless 186 * we run off the end of the instruction store first, at which 187 * point the address register will wrap back to zero. 188 */ 189 for (i = 0; i < 4; i++) { 190 u32 addr; 191 192 addr = ixp2000_uengine_csr_read(uengine, USTORE_ADDRESS); 193 if (addr == 0x80000000) 194 break; 195 ustore_write(uengine, 0xf0000c0300ULL); 196 } 197 198 /* 199 * End programming. 200 */ 201 ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x00000000); 202} 203EXPORT_SYMBOL(ixp2000_uengine_load_microcode); 204 205void ixp2000_uengine_init_context(int uengine, int context, int pc) 206{ 207 /* 208 * Select the right context for indirect access. 209 */ 210 ixp2000_uengine_csr_write(uengine, CSR_CTX_POINTER, context); 211 212 /* 213 * Initialise signal masks to immediately go to Ready state. 214 */ 215 ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_SIG_EVENTS, 1); 216 ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_WAKEUP_EVENTS, 1); 217 218 /* 219 * Set program counter. 220 */ 221 ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_STS, pc); 222} 223EXPORT_SYMBOL(ixp2000_uengine_init_context); 224 225void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask) 226{ 227 u32 mask; 228 229 /* 230 * Enable the specified context to go to Executing state. 231 */ 232 mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); 233 mask |= ctx_mask << 8; 234 ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); 235} 236EXPORT_SYMBOL(ixp2000_uengine_start_contexts); 237 238void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask) 239{ 240 u32 mask; 241 242 /* 243 * Disable the Ready->Executing transition. Note that this 244 * does not stop the context until it voluntarily yields. 245 */ 246 mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); 247 mask &= ~(ctx_mask << 8); 248 ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); 249} 250EXPORT_SYMBOL(ixp2000_uengine_stop_contexts); 251 252static int check_ixp_type(struct ixp2000_uengine_code *c) 253{ 254 u32 product_id; 255 u32 rev; 256 257 product_id = ixp2000_reg_read(IXP_PRODUCT_ID); 258 if (((product_id >> 16) & 0x1f) != 0) 259 return 0; 260 261 switch ((product_id >> 8) & 0xff) { 262#ifdef CONFIG_ARCH_IXP2000 263 case 0: /* IXP2800 */ 264 if (!(c->cpu_model_bitmask & 4)) 265 return 0; 266 break; 267 268 case 1: /* IXP2850 */ 269 if (!(c->cpu_model_bitmask & 8)) 270 return 0; 271 break; 272 273 case 2: /* IXP2400 */ 274 if (!(c->cpu_model_bitmask & 2)) 275 return 0; 276 break; 277#endif 278 279#ifdef CONFIG_ARCH_IXP23XX 280 case 4: /* IXP23xx */ 281 if (!(c->cpu_model_bitmask & 0x3f0)) 282 return 0; 283 break; 284#endif 285 286 default: 287 return 0; 288 } 289 290 rev = product_id & 0xff; 291 if (rev < c->cpu_min_revision || rev > c->cpu_max_revision) 292 return 0; 293 294 return 1; 295} 296 297static void generate_ucode(u8 *ucode, u32 *gpr_a, u32 *gpr_b) 298{ 299 int offset; 300 int i; 301 302 offset = 0; 303 304 for (i = 0; i < 128; i++) { 305 u8 b3; 306 u8 b2; 307 u8 b1; 308 u8 b0; 309 310 b3 = (gpr_a[i] >> 24) & 0xff; 311 b2 = (gpr_a[i] >> 16) & 0xff; 312 b1 = (gpr_a[i] >> 8) & 0xff; 313 b0 = gpr_a[i] & 0xff; 314 315 /* immed[@ai, (b1 << 8) | b0] */ 316 /* 11110000 0000VVVV VVVV11VV VVVVVV00 1IIIIIII */ 317 ucode[offset++] = 0xf0; 318 ucode[offset++] = (b1 >> 4); 319 ucode[offset++] = (b1 << 4) | 0x0c | (b0 >> 6); 320 ucode[offset++] = (b0 << 2); 321 ucode[offset++] = 0x80 | i; 322 323 /* immed_w1[@ai, (b3 << 8) | b2] */ 324 /* 11110100 0100VVVV VVVV11VV VVVVVV00 1IIIIIII */ 325 ucode[offset++] = 0xf4; 326 ucode[offset++] = 0x40 | (b3 >> 4); 327 ucode[offset++] = (b3 << 4) | 0x0c | (b2 >> 6); 328 ucode[offset++] = (b2 << 2); 329 ucode[offset++] = 0x80 | i; 330 } 331 332 for (i = 0; i < 128; i++) { 333 u8 b3; 334 u8 b2; 335 u8 b1; 336 u8 b0; 337 338 b3 = (gpr_b[i] >> 24) & 0xff; 339 b2 = (gpr_b[i] >> 16) & 0xff; 340 b1 = (gpr_b[i] >> 8) & 0xff; 341 b0 = gpr_b[i] & 0xff; 342 343 /* immed[@bi, (b1 << 8) | b0] */ 344 /* 11110000 0000VVVV VVVV001I IIIIII11 VVVVVVVV */ 345 ucode[offset++] = 0xf0; 346 ucode[offset++] = (b1 >> 4); 347 ucode[offset++] = (b1 << 4) | 0x02 | (i >> 6); 348 ucode[offset++] = (i << 2) | 0x03; 349 ucode[offset++] = b0; 350 351 /* immed_w1[@bi, (b3 << 8) | b2] */ 352 /* 11110100 0100VVVV VVVV001I IIIIII11 VVVVVVVV */ 353 ucode[offset++] = 0xf4; 354 ucode[offset++] = 0x40 | (b3 >> 4); 355 ucode[offset++] = (b3 << 4) | 0x02 | (i >> 6); 356 ucode[offset++] = (i << 2) | 0x03; 357 ucode[offset++] = b2; 358 } 359 360 /* ctx_arb[kill] */ 361 ucode[offset++] = 0xe0; 362 ucode[offset++] = 0x00; 363 ucode[offset++] = 0x01; 364 ucode[offset++] = 0x00; 365 ucode[offset++] = 0x00; 366} 367 368static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c) 369{ 370 int per_ctx_regs; 371 u32 *gpr_a; 372 u32 *gpr_b; 373 u8 *ucode; 374 int i; 375 376 gpr_a = kzalloc(128 * sizeof(u32), GFP_KERNEL); 377 gpr_b = kzalloc(128 * sizeof(u32), GFP_KERNEL); 378 ucode = kmalloc(513 * 5, GFP_KERNEL); 379 if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) { 380 kfree(ucode); 381 kfree(gpr_b); 382 kfree(gpr_a); 383 return 1; 384 } 385 386 per_ctx_regs = 16; 387 if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS) 388 per_ctx_regs = 32; 389 390 for (i = 0; i < 256; i++) { 391 struct ixp2000_reg_value *r = c->initial_reg_values + i; 392 u32 *bank; 393 int inc; 394 int j; 395 396 if (r->reg == -1) 397 break; 398 399 bank = (r->reg & 0x400) ? gpr_b : gpr_a; 400 inc = (r->reg & 0x80) ? 128 : per_ctx_regs; 401 402 j = r->reg & 0x7f; 403 while (j < 128) { 404 bank[j] = r->value; 405 j += inc; 406 } 407 } 408 409 generate_ucode(ucode, gpr_a, gpr_b); 410 ixp2000_uengine_load_microcode(uengine, ucode, 513); 411 ixp2000_uengine_init_context(uengine, 0, 0); 412 ixp2000_uengine_start_contexts(uengine, 0x01); 413 for (i = 0; i < 100; i++) { 414 u32 status; 415 416 status = ixp2000_uengine_csr_read(uengine, ACTIVE_CTX_STS); 417 if (!(status & 0x80000000)) 418 break; 419 } 420 ixp2000_uengine_stop_contexts(uengine, 0x01); 421 422 kfree(ucode); 423 kfree(gpr_b); 424 kfree(gpr_a); 425 426 return !!(i == 100); 427} 428 429int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c) 430{ 431 int ctx; 432 433 if (!check_ixp_type(c)) 434 return 1; 435 436 if (!(ixp2000_uengine_mask & (1 << uengine))) 437 return 1; 438 439 ixp2000_uengine_reset(1 << uengine); 440 ixp2000_uengine_set_mode(uengine, c->uengine_parameters); 441 if (set_initial_registers(uengine, c)) 442 return 1; 443 ixp2000_uengine_load_microcode(uengine, c->insns, c->num_insns); 444 445 for (ctx = 0; ctx < 8; ctx++) 446 ixp2000_uengine_init_context(uengine, ctx, 0); 447 448 return 0; 449} 450EXPORT_SYMBOL(ixp2000_uengine_load); 451 452 453static int __init ixp2000_uengine_init(void) 454{ 455 int uengine; 456 u32 value; 457 458 /* 459 * Determine number of microengines present. 460 */ 461 switch ((ixp2000_reg_read(IXP_PRODUCT_ID) >> 8) & 0x1fff) { 462#ifdef CONFIG_ARCH_IXP2000 463 case 0: /* IXP2800 */ 464 case 1: /* IXP2850 */ 465 ixp2000_uengine_mask = 0x00ff00ff; 466 break; 467 468 case 2: /* IXP2400 */ 469 ixp2000_uengine_mask = 0x000f000f; 470 break; 471#endif 472 473#ifdef CONFIG_ARCH_IXP23XX 474 case 4: /* IXP23xx */ 475 ixp2000_uengine_mask = (*IXP23XX_EXP_CFG_FUSE >> 8) & 0xf; 476 break; 477#endif 478 479 default: 480 printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n", 481 (unsigned int)ixp2000_reg_read(IXP_PRODUCT_ID)); 482 ixp2000_uengine_mask = 0x00000000; 483 break; 484 } 485 486 /* 487 * Reset microengines. 488 */ 489 ixp2000_uengine_reset(ixp2000_uengine_mask); 490 491 /* 492 * Synchronise timestamp counters across all microengines. 493 */ 494 value = ixp2000_reg_read(IXP_MISC_CONTROL); 495 ixp2000_reg_wrb(IXP_MISC_CONTROL, value & ~0x80); 496 for (uengine = 0; uengine < 32; uengine++) { 497 if (ixp2000_uengine_mask & (1 << uengine)) { 498 ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0); 499 ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0); 500 } 501 } 502 ixp2000_reg_wrb(IXP_MISC_CONTROL, value | 0x80); 503 504 return 0; 505} 506 507subsys_initcall(ixp2000_uengine_init); 508