Index: linux-2.6.x-petalogix/drivers/block/xsysace.c =================================================================== --- linux-2.6.x-petalogix/drivers/block/xsysace.c (revision 2628) +++ linux-2.6.x-petalogix/drivers/block/xsysace.c (working copy) @@ -73,6 +73,11 @@ * interrupt, then the kernel timer will expire and the driver can * continue where it left off. * + * SystemACE can be wired up in different endian orders and data widths. + * It works on both PPC and MicroBlaze architectures. For this reason, + * an ace_reg_ops structure is used that abstracts away low level + * endian/width/arch access to the HW registers. + * To Do: * - Add FPGA configuration control interface. * - Request major number from lanana @@ -161,32 +166,120 @@ /* --------------------------------------------------------------------- * Low level register access */ +struct reg_ops { + u8 (*read8)(void *addr); + u16 (*read16)(void *addr); + u32 (*read32)(void *addr); + u32 (*readdata)(void *addr); -/* register access macros */ + void (*write16)(void *addr, u16 val); + void (*write32)(void *addr, u32 val); + void (*writedata)(void *addr, u32 val); +}; + +#define ace_reg_read8(ace, reg) (ace->ops->read8(ace->baseaddr + reg)) +#define ace_reg_read16(ace, reg) (ace->ops->read16(ace->baseaddr + reg)) +#define ace_reg_readdata(ace, reg) (ace->ops->readdata(ace->baseaddr + reg)) +#define ace_reg_read32(ace, reg) (ace->ops->read32(ace->baseaddr+reg)) +#define ace_reg_write16(ace, reg, val) (ace->ops->write16(ace->baseaddr+reg, val)) +#define ace_reg_writedata(ace, reg, val) (ace->ops->writedata(ace->baseaddr + reg, val)) +#define ace_reg_write32(ace, reg, val) (ace->ops->write32(ace->baseaddr+reg, val)) + +/* register access functions */ #if 1 /* Little endian 16-bit regs */ -#define ace_reg_read8(ace, reg) in_8(ace->baseaddr + reg) -#define ace_reg_read16(ace, reg) in_le16(ace->baseaddr + reg) -#define ace_reg_readdata(ace, reg) in_be16(ace->baseaddr + reg) -#define ace_reg_read32(ace, reg) ((in_le16(ace->baseaddr + reg+2) << 16) | \ - (in_le16(ace->baseaddr + reg))) -#define ace_reg_write16(ace, reg, val) out_le16(ace->baseaddr + reg, val) -#define ace_reg_writedata(ace, reg, val) out_be16(ace->baseaddr + reg, val) -#define ace_reg_write32(ace, reg, val) { \ - out_le16(ace->baseaddr + reg+2, (val) >> 16); \ - out_le16(ace->baseaddr + reg, val); \ - } +static u8 ace_le16_read8(void *addr) +{ + return in_8(addr); +} + +static u16 ace_le16_read16(void *addr) +{ + return in_le16(addr); +} + +static u32 ace_le16_read32(void *addr) +{ + return ((in_le16(addr+2) << 16) | (in_le16(addr))); +} + +static u32 ace_le16_readdata(void *addr) +{ + return in_be16(addr); +} + +static void ace_le16_write16(void *addr, u16 val) +{ + out_le16(addr, val); +} + +static void ace_le16_write32(void *addr, u32 val) +{ + out_le16(addr+2,(val) >> 16); \ + out_le16(addr, val); +} + +static void ace_le16_writedata(void *addr, u32 val) +{ + out_be16(addr, val); +} + +static struct reg_ops ace_ops = { + .read8 = ace_le16_read8, + .read16 = ace_le16_read16, + .read32 = ace_le16_read32, + .readdata = ace_le16_readdata, + .write16 = ace_le16_write16, + .write32 = ace_le16_write32, + .writedata = ace_le16_writedata +} ; + #else /* Big endian 16-bit regs */ -#define ace_reg_read8(ace, reg) in_8(ace->baseaddr + reg) -#define ace_reg_read16(ace, reg) in_be16(ace->baseaddr + reg) -#define ace_reg_readdata(ace, reg) in_le16(ace->baseaddr + reg) -#define ace_reg_read32(ace, reg) ((in_be16(ace->baseaddr + reg+2) << 16) | \ - (in_be16(ace->baseaddr + reg))) -#define ace_reg_write16(ace, reg, val) out_be16(ace->baseaddr + reg, val) -#define ace_reg_writedata(ace, reg, val) out_le16(ace->baseaddr + reg, val) -#define ace_reg_write32(ace, reg, val) { \ - out_be16(ace->baseaddr + reg+2, (val) >> 16); \ - out_be16(ace->baseaddr + reg, val); \ - } +static u8 ace_be16_read8(void *addr) +{ + return in_8(addr); +} + +static u16 ace_be16_read16(void *addr) +{ + return in_be16(addr); +} + +static u32 ace_be16_read32(void *addr) +{ + return ((in_be16(addr+2) << 16) | (in_be16(addr))); +} + +static u32 ace_be16_readdata(void *addr) +{ + return in_le16(addr); +} + +static void ace_be16_write16(void *addr, u16 val) +{ + out_be16(addr, val); +} + +static void ace_be16_write32(void *addr, u32 val) +{ + out_be16(addr+2,(val) >> 16); \ + out_be16(addr, val); +} + +static void ace_be16_writedata(void *addr, u32 val) +{ + out_le16(addr, val); +} + +static struct reg_ops ace_ops = { + .read8 = ace_be16_read8, + .read16 = ace_be16_read16, + .read32 = ace_be16_read32, + .readdata = ace_be16_readdata, + .write16 = ace_be16_write16, + .write32 = ace_be16_write32, + .writedata = ace_be16_writedata +} ; + #endif struct ace_device { @@ -222,6 +315,9 @@ int bus_width; /* 0 := 8 bit; 1 := 16 bit */ int lock_count; + /* Register access ops */ + struct reg_ops *ops; + /* Block device data structures */ spinlock_t lock; struct device *dev; @@ -995,6 +1091,8 @@ ace->id = dev->id; ace->irq = NO_IRQ; + ace->ops=&ace_ops; + for (i = 0; i < dev->num_resources; i++) { if (dev->resource[i].flags & IORESOURCE_MEM) ace->physaddr = dev->resource[i].start;