/* * Copyright (C) 2006 Claudio Ciccani * * Graphics driver for ATI Radeon cards written by * Claudio Ciccani . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef __RADEON_MMIO_H__ #define __RADEON_MMIO_H__ #include #include #include "radeon.h" static __inline__ void radeon_out8( volatile u8 *mmioaddr, u32 reg, u8 value ) { *((volatile u8*)(mmioaddr+reg)) = value; } static __inline__ void radeon_out16( volatile u8 *mmioaddr, u32 reg, u32 value ) { #ifdef __powerpc__ asm volatile( "sthbrx %0,%1,%2;eieio" :: "r" (value), "b"(reg), "r" (mmioaddr) : "memory" ); #else *((volatile u16*)(mmioaddr+reg)) = value; #endif } static __inline__ void radeon_out32( volatile u8 *mmioaddr, u32 reg, u32 value ) { #ifdef __powerpc__ asm volatile( "stwbrx %0,%1,%2;eieio" :: "r" (value), "b"(reg), "r" (mmioaddr) : "memory" ); #else *((volatile u32*)(mmioaddr+reg)) = value; #endif } static __inline__ u8 radeon_in8( volatile u8 *mmioaddr, u32 reg ) { return *((volatile u8*)(mmioaddr+reg)); } static __inline__ u16 radeon_in16( volatile u8 *mmioaddr, u32 reg ) { #ifdef __powerpc__ u32 value; asm volatile( "lhbrx %0,%1,%2;eieio" : "=r" (value) : "b" (reg), "r" (mmioaddr) ); return value; #else return *((volatile u16*)(mmioaddr+reg)); #endif } static __inline__ u32 radeon_in32( volatile u8 *mmioaddr, u32 reg ) { #ifdef __powerpc__ u32 value; asm volatile( "lwbrx %0,%1,%2;eieio" : "=r" (value) : "b" (reg), "r" (mmioaddr) ); return value; #else return *((volatile u32*)(mmioaddr+reg)); #endif } static __inline__ void radeon_outpll( volatile u8 *mmioaddr, u32 addr, u32 value ) { radeon_out8( mmioaddr, CLOCK_CNTL_INDEX, (addr & 0x3f) | PLL_WR_EN ); radeon_out32( mmioaddr, CLOCK_CNTL_DATA, value ); } static __inline__ u32 radeon_inpll( volatile u8 *mmioaddr, u32 addr ) { radeon_out8( mmioaddr, CLOCK_CNTL_INDEX, addr & 0x3f ); return radeon_in32( mmioaddr, CLOCK_CNTL_DATA ); } static inline bool radeon_waitfifo( RadeonDriverData *rdrv, RadeonDeviceData *rdev, unsigned int space ) { int waitcycles = 0; rdev->waitfifo_sum += space; rdev->waitfifo_calls++; if (rdev->fifo_space < space ) { do { rdev->fifo_space = radeon_in32( rdrv->mmio_base, RBBM_STATUS ); rdev->fifo_space &= RBBM_FIFOCNT_MASK; if (++waitcycles > 10000000) { radeon_reset( rdrv, rdev ); D_BREAK( "FIFO timed out" ); return false; } } while (rdev->fifo_space < space); rdev->fifo_waitcycles += waitcycles; } else rdev->fifo_cache_hits++; rdev->fifo_space -= space; return true; } static inline bool radeon_waitidle( RadeonDriverData *rdrv, RadeonDeviceData *rdev ) { int waitcycles = 0; int status; if (!radeon_waitfifo( rdrv, rdev, 64 )) return false; do { status = radeon_in32( rdrv->mmio_base, RBBM_STATUS ); if (++waitcycles > 10000000) { radeon_reset( rdrv, rdev ); D_BREAK( "Engine timed out" ); return false; } } while (status & RBBM_ACTIVE); rdev->fifo_space = status & RBBM_FIFOCNT_MASK; rdev->idle_waitcycles += waitcycles; return true; } #endif /* __RADEON_MMIO_H__ */