blob: 0f312cb39671e3372b0c3a19581396fbbdfb6aab [file] [log] [blame]
/*
* Copyright (c) 2007, 2008 International Business Machines
* Volkmar Uhlig <vuhlig@us.ibm.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#ifndef __DRIVERS__BLUEGENE__PPC450_H__
#define __DRIVERS__BLUEGENE__PPC450_H__
/* include asm instruction macros */
/* #include <asm/ppc450.h> */
/**********************************************************************
* DCR access wrapper
**********************************************************************/
extern inline uint32_t mfdcrx(uint32_t dcrn)
{
uint32_t value;
asm volatile ("mfdcrx %0,%1": "=r" (value) : "r" (dcrn) : "memory");
return value;
}
extern inline void mtdcrx(uint32_t dcrn, uint32_t value)
{
asm volatile("mtdcrx %0,%1": :"r" (dcrn), "r" (value) : "memory");
}
/* volatile 32bit read */
extern inline uint32_t in_be32_nosync(uint32_t *vaddr)
{
volatile uint32_t *va = (volatile uint32_t *) vaddr;
/* _bgp_mbar(); */
return *va;
}
/**********************************************************************
* Helper functions to access IO via double hummer
**********************************************************************/
extern inline void fpu_memcpy_16(void *dst, void *src)
{
asm volatile("lfpdx 0,0,%0\n"
"stfpdx 0,0,%1\n"
:
: "b"(src), "b"(dst)
: "fr0", "memory");
}
extern inline void out_be128(void *port, void *ptrval)
{
u32 tmp[4] __attribute__((aligned(16)));
if ((u32)ptrval & 0xf) {
memcpy(tmp, ptrval, 16);
ptrval = tmp;
}
fpu_memcpy_16(port, ptrval);
}
extern inline void outs_be128(void *port, void *src, unsigned num)
{
u32 tmp[4] __attribute__((aligned(16)));
/* port must be 16 byte aligned */
BUG_ON((u32)port & 0xf);
if (unlikely((u32)src & 0xf)) {
/* unaligned destination */
while(num--) {
memcpy(tmp, src, 16);
fpu_memcpy_16(port, tmp);
src += 16;
}
} else {
while(num--) {
fpu_memcpy_16(port, src);
src += 16;
}
}
}
extern inline void outs_zero128(void *port, unsigned num)
{
static u32 zero[4] __attribute__((aligned(16))) = {0, };
BUG_ON((u32)port & 0xf);
while (num--)
out_be128(port, zero);
}
/*
* in string operation similar to x86: reads block of data from port
* into memory
*/
extern inline void ins_be128(void *dest, void *port, unsigned num)
{
u32 tmp[4] __attribute__((aligned(16)));
/* port must be 16 byte aligned */
BUG_ON((u32)port & 0xf);
if ((u32)dest & 0xf)
{
/* unaligned destination */
while(num--) {
fpu_memcpy_16(tmp, port);
memcpy(dest, tmp, 16);
dest += 16;
}
}
else
{
while(num--) {
fpu_memcpy_16(dest, port);
dest += 16;
}
}
}
extern inline void in_be128(void *dest, void *port)
{
char tmp[16] __attribute__((aligned(16)));
void *ptr = dest;
if ((u32)dest & 0xf)
ptr = tmp;
fpu_memcpy_16(ptr, port);
if ((u32)dest & 0xf)
memcpy(dest, tmp, 16);
}
#endif /* !__DRIVERS__BLUEGENE__PPC450_H__ */