Jump to content

    
Sign in to follow this  
sabbatazh

Модуль обращения к LocalBus

Recommended Posts

Здравствуйте уважаемые Знатоки!

Прошу вашей помощи!

только познакомился с продукцией Freecale, а именно с процессором MPC8377. и пытаюсь написать модуль доступа к LocalBus, возникла ошибка:

Kernle: module startup...

Kernel: Device registered. Major number is 252

Kernel: mmio =0xd1064000

Machine check in kernel mode.

Caused by (from SRR1=49030): Transfer error ack signal

Oops: Machine check, sig: 7 [#1]

MPC837x RDB

Modules linked in: LocalBus(+) [last unloaded: LocalBus]

NIP: d1084118 LR: d10840f8 CTR: c0208f24

REGS: cfba5dc0 TRAP: 0200 Not tainted (2.6.25)

MSR: 00049030 <EE,ME,IR,DR> CR: 24004428 XER: 00000000

TASK = cf8b4810[1442] 'insmod' THREAD: cfba4000

GPR00: 00000001 cfba5e70 cf8b4810 d1084338 00000000 ffffffff c020c048 00004000

GPR08: 00000034 d1064000 00001ca1 d1002500 24004422 10018d88 0000001d d108246c

GPR16: cf9feb80 d1079254 00000000 0000002d 0000002d d1078cad c003dd7c d1064000

GPR24: 0000001f 0000001f d1078dcc d1084960 00000000 d1084960 cfb34800 d1080000

NIP [d1084118] _init_module+0x9c/0x174 [LocalBus]

LR [d10840f8] _init_module+0x7c/0x174 [LocalBus]

Call Trace:

[cfba5e70] [d10840f8] _init_module+0x7c/0x174 [LocalBus] (unreliable)

[cfba5e80] [c003e6f4] sys_init_module+0x130/0x17b8

[cfba5f40] [c000f70c] ret_from_syscall+0x0/0x38

--- Exception: c01 at 0xff6f218

LR = 0x10000950

Instruction dump:

386342e0 7c040378 901f4ae4 4800009d 813f4ae4 2f890000 419e0074 38000001

3c60d108 98090010 38634338 88890001 <48000079> 813f4ae4 3c60d108 38634344

---[ end trace 8933fae98ac0b4a5 ]---

Bus error

объясняли, что необходимо еще сделать некоторые операции по настройке чипселектов, до меня не дошло! Кто сталкивался с такой штукой подскажите что и как?! Модуль выглядит так:

#define MODULE
#define __KERNEL__

//#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/stddef.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/proc_fs.h>

#include <asm/io.h>
#include <asm/immap_qe.h>
#include <asm/qe.h>


#define DEV_NAME "my_dev"

#define _MBAR_BASE 0xe0000000

#define _CS0_BASE 0xf0000000
#define _CS0_COUNT 0x30

#define _OR0_CFG_VAL 0xFFF00000

#define SUCCESS 0

static int major;
struct file_operations fops;
int _immr_pa;

//unsigned volatile char *mmio;
byte *mmio;
//__be32 __iomem *reg_map;

int _init_module(void )
{
    printk("Kernle: module startup...\n");
    major = register_chrdev(0, DEV_NAME, &fops);
   if (major < 0)
   { // Проверка успешности регистрации
        printk("Kernel: Register failed\n");
        return major;
   };
   printk("Kernel: Device registered. Major number is %d\n",major);

   if(!request_mem_region(_CS0_BASE/*базовый адрес*/, _CS0_COUNT/*размер*/, DEV_NAME));
        {
        //тут ругаемся на то, что ядро не дает память
          printk("Kernel: request_mem_region");
          return 0;
        };

   //reg_map = ioremap_nocache(_CS0_BASE/*базовый адрес*/, _CS0_COUNT/*размер*/);
   mmio = (byte*)ioremap(_CS0_BASE/*базовый адрес*/, _CS0_COUNT/*размер*/);
          printk ("Kernel: mmio =0x%p\n", mmio);

   if (mmio == NULL)
       {
         printk ("Kernel: Could not map base registers at beggining of address=0x%X\n", _CS0_BASE);
         return -ENOMEM;
       };
  
  unsigned int val = 0;

  mmio[0x10] = 1; /*пишем по адресу*/
    printk("Write 0x%p\n", mmio[0x01]);

  val = mmio[0x10];
    printk("Read %d\n", val);

  iounmap(mmio);
}

void _stop_module()
{
   // Снимаем захват памяти
   release_mem_region(_CS0_BASE, _CS0_COUNT);
   printk("Kernel: release memio ports\n");
   // Снимаем регистрацию устройства
   if (unregister_chrdev(major, DEV_NAME) < 0){
       printk("Kernel: unregister device failed\n");
      };
  
  printk("Kernel: device unregistered\n");
  printk("Kernel: module3 is dead \n"); 

return;
}

module_init(_init_module);
module_exit(_stop_module);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Driver CS");

Спасибо!!!

Share this post


Link to post
Share on other sites

Ну да, по-хорошему нада бы еще че-то с железом поделать, т.е. если это LCS[0], то надо прописать регистры BR0 и OR0.

Плюс не забыть сделать local bus window в регистрах LBLAWBAR и LBLAWAR

 

"Transfer error ack" это софт попытался полезть по адресу, который не назначен ни на один из мем контролеров, и не получил transfer acknowledge в положенное время.

Share this post


Link to post
Share on other sites

Спасибо!!!

Делаю драйвер через символьное устройство, нашел подходящий файл структур: immap_83xx.h, и вот теперь опять вопрос возникнул, как правильно заполнить эти структуры:

пробую так, но чет делаю не то:

// MPC83**E UPM setup code on CS3.

//***here FPGA1  base address is defined   on LB (the same as FPGA  base address in previous project)



     #define CFG_FPGA1_BASE        0xF0000000



#define    MBAR_BASE            IMMRBAR_BASE_ADDR  /* #define IMMRBAR_BASE_ADDR 0xe0000000*/



#define LOCAL_BUS_PHYS_ADDR 0xe0005000

#define LOCAL_BUS_SIZE      (64 * 1024 * 1024)
....

// MPC83**E UPM setup code on CS3.
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->lbus.bank[4].br = LOCAL_BUS_PHYS_ADDR | 0x19c1;  // 32-bit, no crc check, read-only, UPMA /* Base Register */

        immrmap->lbus.bank[4].or = 0xfc000001;  // 64MB, /* Option Register */

        immrmap->lbus.mamr = 0x10000000; /* UPMA Mode Register */

        

        printk(KERN_INFO "%s: immrmap->lbus.mamr  %08x\n", __FUNCTION__, (unsigned int)immrmap->lbus.mamr);

          

        eieio();

        udelay(1);

        

    // Write word to RAM arrays

        for(i=0; i<64; i++)

        {

      

                immrmap->lbus.mdr = upm_data_array;/* UPM Data Register */

                eieio();

        }

        

        udelay(1);

        immrmap->lbus.mamr = 0x0; /* UPMA Mode Register */

    eieio();

        udelay(1000);

        return i;

}

обьясните: в файле immap_83xx.h есть структура :

typedef struct lbus_bank {
    u32 br;            /* Base Register */
    u32 or;            /* Option Register */
} lbus_bank_t;
...
lbus_bank_t bank[8];

что она делает и что туда писать?

Share this post


Link to post
Share on other sites

посидев в гугле и с книгами выкрутил модуль, но в нем есть ошибка - не хочет писать и читать или даже не так эти операции проходят не верно при тестировании (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");

Спасибо!

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this