посидев в гугле и с книгами выкрутил модуль, но в нем есть ошибка - не хочет писать и читать или даже не так эти операции проходят не верно при тестировании (test_FPGA1_64regs()), не пойму какая, а можит с инициализациией накрутил (mpc83xx_local_bus_upm_setup()), ПОМОГИТЕ найти:
Код
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <asm/prom.h>
#include <asm/immap_83xx.h>
#include <asm-powerpc/io.h>
#include <asm-powerpc/qe.h>
#define DRIVER_NAME "LocalBus"
#define DRIVER_MAJOR 242
static volatile __be32 __iomem *p_local_bus;
static volatile immap_t *immrbar2;
//***here FPGA1 base address is defined on LB (the same as FPGA base address in previous project)
#define CFG_FPGA1_BASE 0xF0000000
//***here FPGA2 base address is defined on LB (=FPGA1 base address + 512KB)
#define CFG_FPGA2_BASE 0xF0080000
#define MBAR_BASE IMMRBAR_BASE_ADDR /* #define IMMRBAR_BASE_ADDR 0xe0000000*/
#define LOCAL_BUS_PHYS_ADDR 0xe0005000
#define LOCAL_BUS_SIZE (64 * 1024 * 1024)
static unsigned int upm_data_array[] = {
0x00ff3c00, 0x00ff3c00, 0x00ff3c00, 0x00ff3c00, //Words 0 to 3
0x00ff3c00, 0x00ff3c00, 0x00ff3c00, 0x00ff7c05, //Words 4 to 7
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, //Words 8 to 11
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, //Words 12 to 15
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, //Words 16 to 19
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, //Words 20 to 23
0x00fffc00, 0x00fffc00, 0x00fffc00, 0x00fffc04, //Words 24 to 27
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, //Words 28 to 31
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, //Words 32 to 35
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, //Words 36 to 39
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, //Words 40 to 43
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, //Words 44 to 47
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, //Words 48 to 51
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, //Words 52 to 55
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, //Words 56 to 59
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01 //Words 60 to 63
};
// MPC83**E UPM setup code on CS3 and CS4.
int mpc83xx_local_bus_upm_setup(void)
{
unsigned i;
volatile immap_t *immrmap;
printk("mpc83xx_local_bus_upm_setup...\n");
immrmap = immrbar2;
printk(KERN_INFO "%s: immrmap->sysconf.immrbar %08x\n", __FUNCTION__, (unsigned int)immrmap->sysconf.immrbar);
//immrmap->sysconf.immrbar = MBAR_BASE; /* Internal memory map base address register */
immrmap->sysconf.lblaw[2].bar = CFG_FPGA1_BASE; // присвоение физического устройства... /* LBIU local access window base address register */
immrmap->sysconf.lblaw[2].ar = 0x8000000E; //0x80000019; // 64MB /* LBIU local access window attribute register */
immrmap->sysconf.lblaw[3].bar = CFG_FPGA2_BASE; // присвоение физического устройства... /* LBIU local access window base address register */
immrmap->sysconf.lblaw[3].ar = 0x8000000E; //0x80000019; // 64MB /* LBIU local access window attribute register */
//*** Base Adress of the FPGA1; 32bit port; UPMA; "V=>This bank is valid."
immrmap->lbus.bank[2].br = CFG_FPGA1_BASE | 0x1881; // 32-bit, no crc check, read-only, UPMA /* Base Register */
//*** 32KB; EHTR(?); EAD(?); <-two attribute bits from old project
immrmap->lbus.bank[2].or = 0xFFFF8000; /* Option Register */
//*** Base Adress of the FPGA2; 32bit port; UPMA; "V=>This bank is valid."
immrmap->lbus.bank[3].br = CFG_FPGA2_BASE | 0x1881; // 32-bit, no crc check, read-only, UPMA /* Base Register */
//*** 32KB; EHTR(?); EAD(?); <-two attribute bits from old project
immrmap->lbus.bank[3].or = 0xFFFF8000; /* Option Register */
immrmap->lbus.mamr = 0x10000000; /* UPMA Mode Register */
eieio();
udelay(1);
// Write word to RAM arrays
for(i=0; i<64; i++)
{
immrmap->lbus.mdr = upm_data_array[i]; /* UPM Data Register */
eieio();
}
udelay(1);
immrmap->lbus.mamr = 0x00000000; /* UPMA Mode Register */
eieio();
udelay(1000);
return i;
}
int test_driver_open(void)
{
int i;
printk("driver_open called\n");
for(i = 0; i < 4; i++) {
printk(KERN_INFO "%s: immrmap->sysconf.lblaw[%d].bar %08x\n", __FUNCTION__, i, (unsigned int)immrbar2->sysconf.lblaw[i].bar); //tbdrow
printk(KERN_INFO "%s: immrmap->sysconf.lblaw[%d].ar %08x\n", __FUNCTION__, i, (unsigned int)immrbar2->sysconf.lblaw[i].ar); //tbdrow
}
for(i = 0; i < 8; i++) {
printk(KERN_INFO "%s: immrmap->lbus.bank[%d].br %08x\n", __FUNCTION__, i, (unsigned int)immrbar2->lbus.bank[i].br); //tbdrow
printk(KERN_INFO "%s: immrmap->lbus.bank[%d].or %08x\n", __FUNCTION__, i, (unsigned int)immrbar2->lbus.bank[i].or); //tbdrow
}
printk(KERN_INFO "%s: immrmap->lbus.mamr %08x\n", __FUNCTION__, (unsigned int)immrbar2->lbus.mamr); //tbdrow
printk(KERN_INFO "%s: immrmap->lbus.lbcr %08x\n", __FUNCTION__, (unsigned int)immrbar2->lbus.lbcr); //tbdrow
request_mem_region(LOCAL_BUS_PHYS_ADDR, LOCAL_BUS_SIZE, DRIVER_NAME);
/* remap the Local Bus data address */
// p_local_bus = ioremap_nocache(LOCAL_BUS_PHYS_ADDR, LOCAL_BUS_SIZE);
p_local_bus = ioremap_nocache(CFG_FPGA1_BASE, 8000);
return 0;
}
int test_driver_close(void)
{
printk("driver_close called\n");
/* Unmap */
//release_mem_region(LOCAL_BUS_PHYS_ADDR, LOCAL_BUS_SIZE);
//iounmap ((void *)p_local_bus);
iounmap((void *)p_local_bus);
release_mem_region(LOCAL_BUS_PHYS_ADDR, LOCAL_BUS_SIZE);
return 0;
}
/*----------------------------------------------------------------------------------------------------------------------------------*/
void test_FPGA1_64regs(void)
{
u32 tempFPGA_wr=0, tempFPGA_rd=0;
u32 i=0, j=0;
volatile __be32 __iomem *_adr;
for(j=0; j<64;j++) //*** ADDRESS test
{ //***write 4 hi-bits of address to FPGA1 (address of FPGA's AddressRegister on LB =0xF000001C)
//*(u32*)(CFG_FPGA1_BASE | 0x1C) = (j<<2)&0xF0;
_adr = p_local_bus + 0x1C;
out_be32(_adr, (j<<2)&0xF0);
i = ((j <<2) & 0xC);
//*(u32*)(CFG_FPGA1_BASE | i ) = i;
_adr = p_local_bus + i;
out_be32(_adr, i);
//tempFPGA_rd=*(u32*)(CFG_FPGA1_BASE | i );
tempFPGA_rd = in_be32(_adr);
eieio();
if( tempFPGA_rd != i ) printk("FPGA1:[%d] WriteCode = %04x ReadCode = %04x \r\n", j, i, tempFPGA_rd);
}
tempFPGA_wr=0; //additional operator for looking the content of tempFPGA1_rd at the screen
iounmap(_adr);
}
/*----------------------------------------------------------------------------------------------------------------------------------*/
static struct file_operations fops = {
.owner= THIS_MODULE,
// .read= driver_read,
// .open= driver_open,
// .release= driver_close,
};
static int __init mod_init(void)
{
int ret = 0;
int lburet = -1;
struct device_node *np;
struct resource r;
printk("driver_init called\n");
ret = register_chrdev(DRIVER_MAJOR,DRIVER_NAME,&fops);
if( ret != 0 )
{
printk("register_chrdev failed!\n");
return -EIO;
}
printk(KERN_NOTICE "Attempting to connect to MPC83XX Local Bus via UPM\n");
if ((np = of_find_node_by_type(NULL, "soc")) == NULL) {
printk(KERN_INFO "%s: No SOC node in device tree\n", __FUNCTION__);
return -EPERM;
}
memset(&r, 0, sizeof(r));
if (of_address_to_resource(np, 0, &r)) {
printk(KERN_INFO "%s: No SOC reg property in device tree\n", __FUNCTION__);
return -EPERM;
}
immrbar2 = ioremap_nocache(r.start, sizeof(*immrbar2));
/*------------ MPC83**E UPM setup code on CS3 and CS4 ---------------------------------------*/
lburet = mpc83xx_local_bus_upm_setup();
printk(KERN_INFO "%s: local_bus_upm_ret: %#08x\n", __FUNCTION__, lburet);
printk(KERN_NOTICE "Connected to MPC83XX Local Bus via UPM\n");
/*----------------------------------------------------------------------------------------------*/
printk(KERN_NOTICE "TEST...\n");
test_driver_open();
test_FPGA1_64regs();//
test_driver_close();
return 0;
}
static void __exit mod_exit(void)
{
printk("driver_exit called\n");
iounmap(immrbar2);
unregister_chrdev(DRIVER_MAJOR,DRIVER_NAME);
}
module_init(mod_init);
module_exit(mod_exit);
MODULE_AUTHOR("none");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("A generic local bus access device");
MODULE_SUPPORTED_DEVICE("none");
Спасибо!