1225394Sjchandra/*- 2225394Sjchandra * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights 3225394Sjchandra * reserved. 4225394Sjchandra * 5225394Sjchandra * Redistribution and use in source and binary forms, with or without 6225394Sjchandra * modification, are permitted provided that the following conditions are 7225394Sjchandra * met: 8225394Sjchandra * 9225394Sjchandra * 1. Redistributions of source code must retain the above copyright 10225394Sjchandra * notice, this list of conditions and the following disclaimer. 11225394Sjchandra * 2. Redistributions in binary form must reproduce the above copyright 12225394Sjchandra * notice, this list of conditions and the following disclaimer in 13225394Sjchandra * the documentation and/or other materials provided with the 14225394Sjchandra * distribution. 15225394Sjchandra * 16225394Sjchandra * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND 17225394Sjchandra * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18225394Sjchandra * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19225394Sjchandra * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE 20225394Sjchandra * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21225394Sjchandra * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22225394Sjchandra * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23225394Sjchandra * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24225394Sjchandra * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25225394Sjchandra * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26225394Sjchandra * THE POSSIBILITY OF SUCH DAMAGE. 27225394Sjchandra * 28225394Sjchandra * NETLOGIC_BSD 29225394Sjchandra * $FreeBSD$ 30225394Sjchandra */ 31225394Sjchandra 32225394Sjchandra#ifndef __NLM_HAL_MMIO_H__ 33225394Sjchandra#define __NLM_HAL_MMIO_H__ 34225394Sjchandra 35225394Sjchandra/* 36225394Sjchandra * This file contains platform specific memory mapped IO implementation 37225394Sjchandra * and will provide a way to read 32/64 bit memory mapped registers in 38225394Sjchandra * all ABIs 39225394Sjchandra */ 40225394Sjchandra 41225394Sjchandra/* 42225394Sjchandra * For o32 compilation, we have to disable interrupts and enable KX bit to 43225394Sjchandra * access 64 bit addresses or data. 44225394Sjchandra * 45225394Sjchandra * We need to disable interrupts because we save just the lower 32 bits of 46225394Sjchandra * registers in interrupt handling. So if we get hit by an interrupt while 47225394Sjchandra * using the upper 32 bits of a register, we lose. 48225394Sjchandra */ 49225394Sjchandrastatic inline uint32_t nlm_save_flags_kx(void) 50225394Sjchandra{ 51225394Sjchandra uint32_t sr = mips_rd_status(); 52225394Sjchandra 53225394Sjchandra mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX); 54225394Sjchandra return (sr); 55225394Sjchandra} 56225394Sjchandra 57225394Sjchandrastatic inline uint32_t nlm_save_flags_cop2(void) 58225394Sjchandra{ 59225394Sjchandra uint32_t sr = mips_rd_status(); 60225394Sjchandra 61225394Sjchandra mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_COP_2_BIT); 62225394Sjchandra return (sr); 63225394Sjchandra} 64225394Sjchandra 65225394Sjchandrastatic inline void nlm_restore_flags(uint32_t sr) 66225394Sjchandra{ 67225394Sjchandra mips_wr_status(sr); 68225394Sjchandra} 69225394Sjchandra 70225394Sjchandrastatic inline uint32_t 71225394Sjchandranlm_load_word(uint64_t addr) 72225394Sjchandra{ 73225394Sjchandra volatile uint32_t *p = (volatile uint32_t *)(long)addr; 74225394Sjchandra 75225394Sjchandra return *p; 76225394Sjchandra} 77225394Sjchandra 78225394Sjchandrastatic inline void 79225394Sjchandranlm_store_word(uint64_t addr, uint32_t val) 80225394Sjchandra{ 81225394Sjchandra volatile uint32_t *p = (volatile uint32_t *)(long)addr; 82225394Sjchandra 83225394Sjchandra *p = val; 84225394Sjchandra} 85225394Sjchandra 86225394Sjchandra#if defined(__mips_n64) || defined(__mips_n32) 87225394Sjchandrastatic inline uint64_t 88225394Sjchandranlm_load_dword(volatile uint64_t addr) 89225394Sjchandra{ 90225394Sjchandra volatile uint64_t *p = (volatile uint64_t *)(long)addr; 91225394Sjchandra 92225394Sjchandra return *p; 93225394Sjchandra} 94225394Sjchandra 95225394Sjchandrastatic inline void 96225394Sjchandranlm_store_dword(volatile uint64_t addr, uint64_t val) 97225394Sjchandra{ 98225394Sjchandra volatile uint64_t *p = (volatile uint64_t *)(long)addr; 99225394Sjchandra 100225394Sjchandra *p = val; 101225394Sjchandra} 102225394Sjchandra 103225394Sjchandra#else /* o32 */ 104225394Sjchandrastatic inline uint64_t 105225394Sjchandranlm_load_dword(uint64_t addr) 106225394Sjchandra{ 107225394Sjchandra volatile uint64_t *p = (volatile uint64_t *)(long)addr; 108225394Sjchandra uint32_t valhi, vallo, sr; 109225394Sjchandra 110225394Sjchandra sr = nlm_save_flags_kx(); 111225394Sjchandra __asm__ __volatile__( 112225394Sjchandra ".set push\n\t" 113225394Sjchandra ".set mips64\n\t" 114225394Sjchandra "ld $8, 0(%2)\n\t" 115225394Sjchandra "dsra32 %0, $8, 0\n\t" 116225394Sjchandra "sll %1, $8, 0\n\t" 117225394Sjchandra ".set pop\n" 118225394Sjchandra : "=r"(valhi), "=r"(vallo) 119225394Sjchandra : "r"(p) 120225394Sjchandra : "$8"); 121225394Sjchandra nlm_restore_flags(sr); 122225394Sjchandra 123225394Sjchandra return ((uint64_t)valhi << 32) | vallo; 124225394Sjchandra} 125225394Sjchandra 126225394Sjchandrastatic inline void 127225394Sjchandranlm_store_dword(uint64_t addr, uint64_t val) 128225394Sjchandra{ 129225394Sjchandra volatile uint64_t *p = (volatile uint64_t *)(long)addr; 130225394Sjchandra uint32_t valhi, vallo, sr; 131225394Sjchandra 132225394Sjchandra valhi = val >> 32; 133225394Sjchandra vallo = val & 0xffffffff; 134225394Sjchandra 135225394Sjchandra sr = nlm_save_flags_kx(); 136225394Sjchandra __asm__ __volatile__( 137225394Sjchandra ".set push\n\t" 138225394Sjchandra ".set mips64\n\t" 139225394Sjchandra "dsll32 $8, %1, 0\n\t" 140225394Sjchandra "dsll32 $9, %2, 0\n\t" /* get rid of the */ 141225394Sjchandra "dsrl32 $9, $9, 0\n\t" /* sign extend */ 142225394Sjchandra "or $9, $9, $8\n\t" 143225394Sjchandra "sd $9, 0(%0)\n\t" 144225394Sjchandra ".set pop\n" 145225394Sjchandra : : "r"(p), "r"(valhi), "r"(vallo) 146225394Sjchandra : "$8", "$9", "memory"); 147225394Sjchandra nlm_restore_flags(sr); 148225394Sjchandra} 149225394Sjchandra#endif 150225394Sjchandra 151225394Sjchandra#if defined(__mips_n64) 152225394Sjchandrastatic inline uint64_t 153225394Sjchandranlm_load_word_daddr(uint64_t addr) 154225394Sjchandra{ 155225394Sjchandra volatile uint32_t *p = (volatile uint32_t *)(long)addr; 156225394Sjchandra 157225394Sjchandra return *p; 158225394Sjchandra} 159225394Sjchandra 160225394Sjchandrastatic inline void 161225394Sjchandranlm_store_word_daddr(uint64_t addr, uint32_t val) 162225394Sjchandra{ 163225394Sjchandra volatile uint32_t *p = (volatile uint32_t *)(long)addr; 164225394Sjchandra 165225394Sjchandra *p = val; 166225394Sjchandra} 167225394Sjchandra 168225394Sjchandrastatic inline uint64_t 169225394Sjchandranlm_load_dword_daddr(uint64_t addr) 170225394Sjchandra{ 171225394Sjchandra volatile uint64_t *p = (volatile uint64_t *)(long)addr; 172225394Sjchandra 173225394Sjchandra return *p; 174225394Sjchandra} 175225394Sjchandra 176225394Sjchandrastatic inline void 177225394Sjchandranlm_store_dword_daddr(uint64_t addr, uint64_t val) 178225394Sjchandra{ 179225394Sjchandra volatile uint64_t *p = (volatile uint64_t *)(long)addr; 180225394Sjchandra 181225394Sjchandra *p = val; 182225394Sjchandra} 183225394Sjchandra 184225394Sjchandra#elif defined(__mips_n32) 185225394Sjchandra 186225394Sjchandrastatic inline uint64_t 187225394Sjchandranlm_load_word_daddr(uint64_t addr) 188225394Sjchandra{ 189225394Sjchandra uint32_t val; 190225394Sjchandra 191225394Sjchandra __asm__ __volatile__( 192225394Sjchandra ".set push\n\t" 193225394Sjchandra ".set mips64\n\t" 194225394Sjchandra "lw %0, 0(%1)\n\t" 195225394Sjchandra ".set pop\n" 196225394Sjchandra : "=r"(val) 197225394Sjchandra : "r"(addr)); 198225394Sjchandra 199225394Sjchandra return val; 200225394Sjchandra} 201225394Sjchandra 202225394Sjchandrastatic inline void 203225394Sjchandranlm_store_word_daddr(uint64_t addr, uint32_t val) 204225394Sjchandra{ 205225394Sjchandra __asm__ __volatile__( 206225394Sjchandra ".set push\n\t" 207225394Sjchandra ".set mips64\n\t" 208225394Sjchandra "sw %0, 0(%1)\n\t" 209225394Sjchandra ".set pop\n" 210225394Sjchandra : : "r"(val), "r"(addr) 211225394Sjchandra : "memory"); 212225394Sjchandra} 213225394Sjchandra 214225394Sjchandrastatic inline uint64_t 215225394Sjchandranlm_load_dword_daddr(uint64_t addr) 216225394Sjchandra{ 217225394Sjchandra uint64_t val; 218225394Sjchandra 219225394Sjchandra __asm__ __volatile__( 220225394Sjchandra ".set push\n\t" 221225394Sjchandra ".set mips64\n\t" 222225394Sjchandra "ld %0, 0(%1)\n\t" 223225394Sjchandra ".set pop\n" 224225394Sjchandra : "=r"(val) 225225394Sjchandra : "r"(addr)); 226225394Sjchandra return val; 227225394Sjchandra} 228225394Sjchandra 229225394Sjchandrastatic inline void 230225394Sjchandranlm_store_dword_daddr(uint64_t addr, uint64_t val) 231225394Sjchandra{ 232225394Sjchandra __asm__ __volatile__( 233225394Sjchandra ".set push\n\t" 234225394Sjchandra ".set mips64\n\t" 235225394Sjchandra "sd %0, 0(%1)\n\t" 236225394Sjchandra ".set pop\n" 237225394Sjchandra : : "r"(val), "r"(addr) 238225394Sjchandra : "memory"); 239225394Sjchandra} 240225394Sjchandra 241225394Sjchandra#else /* o32 */ 242225394Sjchandrastatic inline uint64_t 243225394Sjchandranlm_load_word_daddr(uint64_t addr) 244225394Sjchandra{ 245225394Sjchandra uint32_t val, addrhi, addrlo, sr; 246225394Sjchandra 247225394Sjchandra addrhi = addr >> 32; 248225394Sjchandra addrlo = addr & 0xffffffff; 249225394Sjchandra 250225394Sjchandra sr = nlm_save_flags_kx(); 251225394Sjchandra __asm__ __volatile__( 252225394Sjchandra ".set push\n\t" 253225394Sjchandra ".set mips64\n\t" 254225394Sjchandra "dsll32 $8, %1, 0\n\t" 255225394Sjchandra "dsll32 $9, %2, 0\n\t" 256225394Sjchandra "dsrl32 $9, $9, 0\n\t" 257225394Sjchandra "or $9, $9, $8\n\t" 258225394Sjchandra "lw %0, 0($9)\n\t" 259225394Sjchandra ".set pop\n" 260225394Sjchandra : "=r"(val) 261225394Sjchandra : "r"(addrhi), "r"(addrlo) 262225394Sjchandra : "$8", "$9"); 263225394Sjchandra nlm_restore_flags(sr); 264225394Sjchandra 265225394Sjchandra return val; 266225394Sjchandra 267225394Sjchandra} 268225394Sjchandra 269225394Sjchandrastatic inline void 270225394Sjchandranlm_store_word_daddr(uint64_t addr, uint32_t val) 271225394Sjchandra{ 272225394Sjchandra uint32_t addrhi, addrlo, sr; 273225394Sjchandra 274225394Sjchandra addrhi = addr >> 32; 275225394Sjchandra addrlo = addr & 0xffffffff; 276225394Sjchandra 277225394Sjchandra sr = nlm_save_flags_kx(); 278225394Sjchandra __asm__ __volatile__( 279225394Sjchandra ".set push\n\t" 280225394Sjchandra ".set mips64\n\t" 281225394Sjchandra "dsll32 $8, %1, 0\n\t" 282225394Sjchandra "dsll32 $9, %2, 0\n\t" 283225394Sjchandra "dsrl32 $9, $9, 0\n\t" 284225394Sjchandra "or $9, $9, $8\n\t" 285225394Sjchandra "sw %0, 0($9)\n\t" 286225394Sjchandra ".set pop\n" 287225394Sjchandra : : "r"(val), "r"(addrhi), "r"(addrlo) 288225394Sjchandra : "$8", "$9", "memory"); 289225394Sjchandra nlm_restore_flags(sr); 290225394Sjchandra} 291225394Sjchandra 292225394Sjchandrastatic inline uint64_t 293225394Sjchandranlm_load_dword_daddr(uint64_t addr) 294225394Sjchandra{ 295225394Sjchandra uint32_t addrh, addrl, sr; 296225394Sjchandra uint32_t valh, vall; 297225394Sjchandra 298225394Sjchandra addrh = addr >> 32; 299225394Sjchandra addrl = addr & 0xffffffff; 300225394Sjchandra 301225394Sjchandra sr = nlm_save_flags_kx(); 302225394Sjchandra __asm__ __volatile__( 303225394Sjchandra ".set push\n\t" 304225394Sjchandra ".set mips64\n\t" 305225394Sjchandra "dsll32 $8, %2, 0\n\t" 306225394Sjchandra "dsll32 $9, %3, 0\n\t" 307225394Sjchandra "dsrl32 $9, $9, 0\n\t" 308225394Sjchandra "or $9, $9, $8\n\t" 309225394Sjchandra "ld $8, 0($9)\n\t" 310225394Sjchandra "dsra32 %0, $8, 0\n\t" 311225394Sjchandra "sll %1, $8, 0\n\t" 312225394Sjchandra ".set pop\n" 313225394Sjchandra : "=r"(valh), "=r"(vall) 314225394Sjchandra : "r"(addrh), "r"(addrl) 315225394Sjchandra : "$8", "$9"); 316225394Sjchandra nlm_restore_flags(sr); 317225394Sjchandra 318225394Sjchandra return ((uint64_t)valh << 32) | vall; 319225394Sjchandra} 320225394Sjchandra 321225394Sjchandrastatic inline void 322225394Sjchandranlm_store_dword_daddr(uint64_t addr, uint64_t val) 323225394Sjchandra{ 324225394Sjchandra uint32_t addrh, addrl, sr; 325225394Sjchandra uint32_t valh, vall; 326225394Sjchandra 327225394Sjchandra addrh = addr >> 32; 328225394Sjchandra addrl = addr & 0xffffffff; 329225394Sjchandra valh = val >> 32; 330225394Sjchandra vall = val & 0xffffffff; 331225394Sjchandra 332225394Sjchandra sr = nlm_save_flags_kx(); 333225394Sjchandra __asm__ __volatile__( 334225394Sjchandra ".set push\n\t" 335225394Sjchandra ".set mips64\n\t" 336225394Sjchandra "dsll32 $8, %2, 0\n\t" 337225394Sjchandra "dsll32 $9, %3, 0\n\t" 338225394Sjchandra "dsrl32 $9, $9, 0\n\t" 339225394Sjchandra "or $9, $9, $8\n\t" 340225394Sjchandra "dsll32 $8, %0, 0\n\t" 341225394Sjchandra "dsll32 $10, %1, 0\n\t" 342225394Sjchandra "dsrl32 $10, $10, 0\n\t" 343225394Sjchandra "or $8, $8, $10\n\t" 344225394Sjchandra "sd $8, 0($9)\n\t" 345225394Sjchandra ".set pop\n" 346225394Sjchandra : : "r"(valh), "r"(vall), "r"(addrh), "r"(addrl) 347225394Sjchandra : "$8", "$9", "memory"); 348225394Sjchandra nlm_restore_flags(sr); 349225394Sjchandra} 350225394Sjchandra#endif /* __mips_n64 */ 351225394Sjchandra 352225394Sjchandrastatic inline uint32_t 353225394Sjchandranlm_read_reg(uint64_t base, uint32_t reg) 354225394Sjchandra{ 355225394Sjchandra volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg; 356225394Sjchandra 357225394Sjchandra return *addr; 358225394Sjchandra} 359225394Sjchandra 360225394Sjchandrastatic inline void 361225394Sjchandranlm_write_reg(uint64_t base, uint32_t reg, uint32_t val) 362225394Sjchandra{ 363225394Sjchandra volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg; 364225394Sjchandra 365225394Sjchandra *addr = val; 366225394Sjchandra} 367225394Sjchandra 368225394Sjchandrastatic inline uint64_t 369225394Sjchandranlm_read_reg64(uint64_t base, uint32_t reg) 370225394Sjchandra{ 371225394Sjchandra uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); 372225394Sjchandra 373225394Sjchandra return nlm_load_dword(addr); 374225394Sjchandra} 375225394Sjchandra 376225394Sjchandrastatic inline void 377225394Sjchandranlm_write_reg64(uint64_t base, uint32_t reg, uint64_t val) 378225394Sjchandra{ 379225394Sjchandra uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); 380225394Sjchandra 381225394Sjchandra return nlm_store_dword(addr, val); 382225394Sjchandra} 383225394Sjchandra 384225394Sjchandra/* 385225394Sjchandra * Routines to store 32/64 bit values to 64 bit addresses, 386225394Sjchandra * used when going thru XKPHYS to access registers 387225394Sjchandra */ 388225394Sjchandrastatic inline uint32_t 389225394Sjchandranlm_read_reg_xkphys(uint64_t base, uint32_t reg) 390225394Sjchandra{ 391225394Sjchandra uint64_t addr = base + reg * sizeof(uint32_t); 392225394Sjchandra 393225394Sjchandra return nlm_load_word_daddr(addr); 394225394Sjchandra} 395225394Sjchandra 396225394Sjchandrastatic inline void 397225394Sjchandranlm_write_reg_xkphys(uint64_t base, uint32_t reg, uint32_t val) 398225394Sjchandra{ 399225394Sjchandra uint64_t addr = base + reg * sizeof(uint32_t); 400225394Sjchandra return nlm_store_word_daddr(addr, val); 401225394Sjchandra} 402225394Sjchandra 403225394Sjchandrastatic inline uint64_t 404225394Sjchandranlm_read_reg64_xkphys(uint64_t base, uint32_t reg) 405225394Sjchandra{ 406225394Sjchandra uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); 407225394Sjchandra 408225394Sjchandra return nlm_load_dword_daddr(addr); 409225394Sjchandra} 410225394Sjchandra 411225394Sjchandrastatic inline void 412225394Sjchandranlm_write_reg64_xkphys(uint64_t base, uint32_t reg, uint64_t val) 413225394Sjchandra{ 414225394Sjchandra uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); 415225394Sjchandra 416225394Sjchandra return nlm_store_dword_daddr(addr, val); 417225394Sjchandra} 418225394Sjchandra 419225394Sjchandra/* Location where IO base is mapped */ 420225394Sjchandraextern uint64_t xlp_io_base; 421225394Sjchandra 422225394Sjchandrastatic inline uint64_t 423225394Sjchandranlm_pcicfg_base(uint32_t devoffset) 424225394Sjchandra{ 425225394Sjchandra return xlp_io_base + devoffset; 426225394Sjchandra} 427225394Sjchandra 428225394Sjchandrastatic inline uint64_t 429225394Sjchandranlm_xkphys_map_pcibar0(uint64_t pcibase) 430225394Sjchandra{ 431225394Sjchandra uint64_t paddr; 432225394Sjchandra 433225394Sjchandra paddr = nlm_read_reg(pcibase, 0x4) & ~0xfu; 434225394Sjchandra return (uint64_t)0x9000000000000000 | paddr; 435225394Sjchandra} 436225394Sjchandra 437225394Sjchandra#endif 438