Jump to content

    

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

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

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

только познакомился с продукцией 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

а и столкнулся с такой какой как mmu, что с ней делать? как ее проинициализировать?

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this