blob: b1cbf8bb923244b40fc8804bd8f6cd663b0c4650 [file] [log] [blame]
/****************************************************************************/
/*
* linux/include/asm-m68knommu/ide.h
*
* Copyright (C) 1994-1996 Linus Torvalds & authors
* Copyright (C) 2001 Lineo Inc., davidm@uclinux.org
*/
/****************************************************************************/
#ifndef _M68KNOMMU_IDE_H
#define _M68KNOMMU_IDE_H
#ifdef __KERNEL__
/****************************************************************************/
#include <linux/config.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/io.h>
#include <asm/irq.h>
/****************************************************************************/
/*
* some coldfire specifics
*/
#ifdef CONFIG_COLDFIRE
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
/*
* Save some space, only have 1 interface
*/
#define MAX_HWIFS 1 /* we only have one interface for now */
#ifdef CONFIG_SECUREEDGEMP3
#define MCFSIM_LOCALCS MCFSIM_CSCR4
#else
#define MCFSIM_LOCALCS MCFSIM_CSCR6
#endif
#endif /* CONFIG_COLDFIRE */
/****************************************************************************/
/*
* Fix up things that may not have been provided
*/
#ifndef MAX_HWIFS
#define MAX_HWIFS 4 /* same as the other archs */
#endif
#undef SUPPORT_SLOW_DATA_PORTS
#define SUPPORT_SLOW_DATA_PORTS 0
#undef SUPPORT_VLB_SYNC
#define SUPPORT_VLB_SYNC 0
/* this definition is used only on startup .. */
#undef HD_DATA
#define HD_DATA NULL
#define DBGIDE(fmt,a...)
// #define DBGIDE(fmt,a...) printk(fmt, ##a)
#define IDE_INLINE __inline__
// #define IDE_INLINE
/****************************************************************************/
typedef union {
unsigned all : 8; /* all of the bits together */
struct {
unsigned bit7 : 1; /* always 1 */
unsigned lba : 1; /* using LBA instead of CHS */
unsigned bit5 : 1; /* always 1 */
unsigned unit : 1; /* drive select number, 0 or 1 */
unsigned head : 4; /* always zeros here */
} b;
} select_t;
/*
* our list of ports/irq's for different boards
*/
static struct m68k_ide_defaults {
ide_ioreg_t base;
int irq;
} m68k_ide_defaults[MAX_HWIFS] = {
#if defined(CONFIG_SECUREEDGEMP3)
{ ((ide_ioreg_t)0x30800000), 29 },
#elif defined(CONFIG_eLIA)
{ ((ide_ioreg_t)0x30c00000), 29 },
#else
{ ((ide_ioreg_t)0x0), 0 }
#endif
};
/****************************************************************************/
static IDE_INLINE int ide_default_irq(ide_ioreg_t base)
{
int i;
for (i = 0; i < MAX_HWIFS; i++)
if (m68k_ide_defaults[i].base == base)
return(m68k_ide_defaults[i].irq);
return 0;
}
static IDE_INLINE ide_ioreg_t ide_default_io_base(int index)
{
if (index >= 0 && index < MAX_HWIFS)
return(m68k_ide_defaults[index].base);
return 0;
}
/*
* Set up a hw structure for a specified data port, control port and IRQ.
* This should follow whatever the default interface uses.
*/
static IDE_INLINE void ide_init_hwif_ports(
hw_regs_t *hw,
ide_ioreg_t data_port,
ide_ioreg_t ctrl_port,
int *irq)
{
ide_ioreg_t reg = data_port;
int i;
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
hw->io_ports[i] = reg;
reg += 1;
}
if (ctrl_port) {
hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
} else {
hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0xe;
}
}
#define ide_init_default_irq(base) ide_default_irq(base)
static IDE_INLINE int
ide_request_irq(
unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long flags,
const char *device,
void *dev_id)
{
#ifdef CONFIG_COLDFIRE
mcf_autovector(irq);
#endif
return(request_irq(irq, handler, flags, device, dev_id));
}
static IDE_INLINE void
ide_free_irq(unsigned int irq, void *dev_id)
{
free_irq(irq, dev_id);
}
static IDE_INLINE int
ide_check_region(ide_ioreg_t from, unsigned int extent)
{
return 0;
}
static IDE_INLINE void
ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name)
{
}
static IDE_INLINE void
ide_release_region(ide_ioreg_t from, unsigned int extent)
{
}
static IDE_INLINE void
ide_fix_driveid(struct hd_driveid *id)
{
#ifdef CONFIG_COLDFIRE
int i, n;
unsigned short *wp = (unsigned short *) id;
int avoid[] = {49, 51, 52, 59, -1 }; /* do not swap these words */
/* Need to byte swap shorts, but not char fields */
for (i = n = 0; i < sizeof(*id) / sizeof(*wp); i++, wp++) {
if (avoid[n] == i) {
n++;
continue;
}
*wp = ((*wp & 0xff) << 8) | ((*wp >> 8) & 0xff);
}
/* have to word swap the one 32 bit field */
id->lba_capacity = ((id->lba_capacity & 0xffff) << 16) |
((id->lba_capacity >> 16) & 0xffff);
#endif
}
static IDE_INLINE void
ide_release_lock (int *ide_lock)
{
}
static IDE_INLINE void
ide_get_lock(
int *ide_lock,
void (*handler)(int, void *, struct pt_regs *),
void *data)
{
}
#define ide_ack_intr(hwif) \
((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)
#define ide__sti() __sti()
/****************************************************************************/
/*
* System specific IO requirements
*/
#ifdef CONFIG_COLDFIRE
#ifdef CONFIG_SECUREEDGEMP3
/* Replace standard IO functions for funky mapping of MP3 board */
#undef outb
#undef outb_p
#undef inb
#undef inb_p
#define outb(v, a) ide_outb(v, (unsigned long) (a))
#define outb_p(v, a) ide_outb(v, (unsigned long) (a))
#define inb(a) ide_inb((unsigned long) (a))
#define inb_p(a) ide_inb((unsigned long) (a))
#define ADDR8_PTR(addr) (((addr) & 0x1) ? (0x8000 + (addr) - 1) : (addr))
#define ADDR16_PTR(addr) (addr)
#define ADDR32_PTR(addr) (addr)
#define SWAP8(w) ((((w) & 0xffff) << 8) | (((w) & 0xffff) >> 8))
#define SWAP16(w) (w)
#define SWAP32(w) (w)
static IDE_INLINE void
ide_outb(unsigned int val, unsigned int addr)
{
volatile unsigned short *rp;
DBGIDE("%s(val=%x,addr=%x)\n", __FUNCTION__, val, addr);
rp = (volatile unsigned short *) ADDR8_PTR(addr);
*rp = SWAP8(val);
}
static IDE_INLINE int
ide_inb(unsigned int addr)
{
volatile unsigned short *rp, val;
DBGIDE("%s(addr=%x)\n", __FUNCTION__, addr);
rp = (volatile unsigned short *) ADDR8_PTR(addr);
val = *rp;
return(SWAP8(val));
}
static IDE_INLINE void
ide_outw(unsigned int val, unsigned int addr)
{
volatile unsigned short *rp;
DBGIDE("%s(val=%x,addr=%x)\n", __FUNCTION__, val, addr);
rp = (volatile unsigned short *) ADDR16_PTR(addr);
*rp = SWAP16(val);
}
static IDE_INLINE void
ide_outsw(unsigned int addr, const void *vbuf, unsigned long len)
{
volatile unsigned short *rp, val;
unsigned short *buf;
DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len);
buf = (unsigned short *) vbuf;
rp = (volatile unsigned short *) ADDR16_PTR(addr);
for (; (len > 0); len--) {
val = *buf++;
*rp = SWAP16(val);
}
}
static IDE_INLINE int
ide_inw(unsigned int addr)
{
volatile unsigned short *rp, val;
DBGIDE("%s(addr=%x)\n", __FUNCTION__, addr);
rp = (volatile unsigned short *) ADDR16_PTR(addr);
val = *rp;
return(SWAP16(val));
}
static IDE_INLINE void
ide_insw(unsigned int addr, void *vbuf, unsigned long len)
{
volatile unsigned short *rp;
unsigned short w, *buf;
DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len);
buf = (unsigned short *) vbuf;
rp = (volatile unsigned short *) ADDR16_PTR(addr);
for (; (len > 0); len--) {
w = *rp;
*buf++ = SWAP16(w);
}
}
static IDE_INLINE void
ide_insl(unsigned int addr, void *vbuf, unsigned long len)
{
volatile unsigned long *rp;
unsigned long w, *buf;
DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len);
buf = (unsigned long *) vbuf;
rp = (volatile unsigned long *) ADDR32_PTR(addr);
for (; (len > 0); len--) {
w = *rp;
*buf++ = SWAP32(w);
}
}
static IDE_INLINE void
ide_outsl(unsigned int addr, const void *vbuf, unsigned long len)
{
volatile unsigned long *rp, val;
unsigned long *buf;
DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len);
buf = (unsigned long *) vbuf;
rp = (volatile unsigned long *) ADDR32_PTR(addr);
for (; (len > 0); len--) {
val = *buf++;
*rp = SWAP32(val);
}
}
#elif CONFIG_eLIA
/* 8/16 bit acesses are controlled by flicking bits in the CS register */
#define ACCESS_MODE_16BIT() \
*((volatile unsigned short *) (MCF_MBAR + MCFSIM_LOCALCS)) = 0x0080
#define ACCESS_MODE_8BIT() \
*((volatile unsigned short *) (MCF_MBAR + MCFSIM_LOCALCS)) = 0x0040
static IDE_INLINE void
ide_outw(unsigned int val, unsigned int addr)
{
ACCESS_MODE_16BIT();
outw(val, addr);
ACCESS_MODE_8BIT();
}
static IDE_INLINE void
ide_outsw(unsigned int addr, const void *vbuf, unsigned long len)
{
ACCESS_MODE_16BIT();
outsw(addr, vbuf, len);
ACCESS_MODE_8BIT();
}
static IDE_INLINE int
ide_inw(unsigned int addr)
{
int ret;
ACCESS_MODE_16BIT();
ret = inw(addr);
ACCESS_MODE_8BIT();
return(ret);
}
static IDE_INLINE void
ide_insw(unsigned int addr, void *vbuf, unsigned long len)
{
ACCESS_MODE_16BIT();
insw(addr, vbuf, len);
ACCESS_MODE_8BIT();
}
static IDE_INLINE void
ide_insl(unsigned int addr, void *vbuf, unsigned long len)
{
ACCESS_MODE_16BIT();
insl(addr, vbuf, len);
ACCESS_MODE_8BIT();
}
static IDE_INLINE void
ide_outsl(unsigned int addr, const void *vbuf, unsigned long len)
{
ACCESS_MODE_16BIT();
outsl(addr, vbuf, len);
ACCESS_MODE_8BIT();
}
#endif /* CONFIG_SECUREEDGEMP3 */
#undef outw
#undef outw_p
#undef outsw
#undef inw
#undef inw_p
#undef insw
#undef insl
#undef outsl
#define outw(v, a) ide_outw(v, (unsigned long) (a))
#define outw_p(v, a) ide_outw(v, (unsigned long) (a))
#define outsw(a, b, n) ide_outsw((unsigned long) (a), b, n)
#define inw(a) ide_inw((unsigned long) (a))
#define inw_p(a) ide_inw((unsigned long) (a))
#define insw(a, b, n) ide_insw((unsigned long) (a), b, n)
#define insl(a, b, n) ide_insl((unsigned long) (a), b, n)
#define outsl(a, b, n) ide_outsl((unsigned long) (a), b, n)
#endif CONFIG_COLDFIRE
/****************************************************************************/
#endif /* __KERNEL__ */
#endif /* _M68KNOMMU_IDE_H */
/****************************************************************************/