]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/mpc5200.c
MPC5200 with MSCAN - Beta version
[lincan.git] / lincan / src / mpc5200.c
index 10d23a1406872d534ff1664b69ea4b60226b802b..2e159cc1ae89f6ddc87758f5dce987a61ad32fe2 100644 (file)
 #include "../include/main.h"
 #include "../include/mpc5200.h"
 #include "../include/mscan.h"
+#include "linux/of.h"
+#include "linux/of_platform.h"
+
+int mpc5200_init_device_node(struct canchip_t * chip, struct device_node * devnode);
+
+/* in time when release_io should take place, we dont know the
+ * base addresses that has to be free.
+ * This variable keeps those addresses
+ */
+unsigned long * chips_addr;
+
 
 int mpc5200_request_io(struct candevice_t *candev)
 {
-       if (!can_request_io_region(candev->io_addr, candev->nr_all_chips * IO_RANGE, DEVICE_NAME)) {
-               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
-               return -ENODEV;
+       int chipnr;
+       struct device_node * dn;
+       const char * of_devname = "can";
+
+       /* Workaround for OpenFormware */
+
+       /* Select device by chipnr:
+        *  first dev is @ 900
+        *  second dev is @ 980
+        * 
+        * There are only two devices on MPC5200 */
+
+       /* initialize internal address storage */
+       chips_addr = (unsigned long*)kmalloc(candev->nr_all_chips * sizeof(unsigned long), GFP_KERNEL);
+
+       /* DEBUGMSG("Looking for device node '%s'\n", of_devname); */
+
+       chipnr = 0;
+       for_each_node_by_name(dn, of_devname)
+       {
+               /* DEBUGMSG(" got OF node (%s)...\n", of_devname); */
+
+               if (!of_device_is_available(dn))
+               {
+                       DEBUGMSG("\tdevice not available\n");
+                       continue;
+               }
+
+               
+               if (mpc5200_init_device_node(candev->chip[chipnr], dn))
+                       return -ENODEV;
+
+               /* fill received address to internal storage */
+               chips_addr[chipnr] = (unsigned long)candev->chip[chipnr]->chip_base_addr;
+
+               /* original MIDAM Shark board use only one CAN chip - this handles similar cases */
+               if (++chipnr >= candev->nr_all_chips)
+                       break;
        }
 
-       DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + candev->nr_all_chips * IO_RANGE - 1);
+
+       DEBUGMSG("Succesfully mapped %d can devices\n", chipnr);
        return 0;
 }
 
 int mpc5200_release_io(struct candevice_t *candev)
 {
-       can_release_io_region(candev->io_addr, candev->nr_all_chips * IO_RANGE);
+       int i;
 
+       /*can_release_io_region(candev->io_addr, candev->nr_all_chips * IO_RANGE);*/
+
+       /* free all chips memorey space - using internal address storage */
+       for (i = 0; i < candev->nr_all_chips; i++)
+               iounmap((void*)chips_addr[i]);
+       
        return 0;
 }
 
@@ -65,7 +118,8 @@ int mpc5200_reset(struct candevice_t *candev)
        for (i = 0; i < candev->nr_all_chips; i++)
        {
            /* !!! Assuming this card has ONLY MSCAN chips !!! */
-           if (mscan_reset_chip(candev->chip[i])) return -ENODEV;
+           if (mscan_reset_chip(candev->chip[i]))
+               return -ENODEV;
        }
 
        return 0;
@@ -85,11 +139,15 @@ int mpc5200_init_chip_data(struct candevice_t *candev, int chipnr)
 {
        mscan_fill_chipspecops(candev->chip[chipnr]);
 
-       candev->chip[chipnr]->chip_base_addr = can_ioport2ioptr(candev->io_addr) + chipnr * MPC5200_CAN_CHIP_OFFSET; /* one chip with 2 interfaces */
        candev->chip[chipnr]->clock = MPC5200_CLK_FREQ;
-       candev->chip[chipnr]->chip_irq = MPC5200_CAN_IRQ + chipnr;
        candev->chip[chipnr]->hostdevice = candev;
 
+/*
+       candev->chip[chipnr]->chip_base_addr = can_ioport2ioptr(candev->io_addr) + chipnr * MPC5200_CAN_CHIP_OFFSET;  one chip with 2 interfaces
+       candev->chip[chipnr]->chip_irq = MPC5200_CAN_IRQ + chipnr;
+*/
+       DEBUGMSG("mpc5200_init_chip_data\n");
+
        return 0;
 }
 
@@ -111,14 +169,14 @@ int mpc5200_program_irq(struct candevice_t *candev)
 void mpc5200_write_register(unsigned data, can_ioptr_t address)
 {
        /* address is an absolute address */
-       DEBUGMSG("write register\n");
+       /* DEBUGMSG("write register\n"); */
        writeb(data, address);          /* regs in PowerPC (5200) are one-byte length */
 }
 
 unsigned mpc5200_read_register(can_ioptr_t address)
 {
        /* address is an absolute address */
-       DEBUGMSG("read register\n");
+       /* DEBUGMSG("read register\n"); */
        return readb(address);          /* regs in PowerPC (5200) are one-byte length */
 }
 
@@ -130,8 +188,31 @@ int mpc5200_register(struct hwspecops_t *hwspecops)
        hwspecops->init_hw_data = mpc5200_init_hw_data;
        hwspecops->init_chip_data = mpc5200_init_chip_data;
        hwspecops->init_obj_data = mpc5200_init_obj_data;
-       hwspecops->program_irq = mpc5200_program_irq;
+       hwspecops->program_irq = NULL; /* mpc5200_program_irq; */
        hwspecops->write_register = mpc5200_write_register;
        hwspecops->read_register = mpc5200_read_register;
        return 0;
 }
+
+
+int mpc5200_init_device_node(struct canchip_t * chip, struct device_node * devnode)
+{
+       chip->chip_base_addr = of_iomap(devnode, 0);
+       if (!chip->chip_base_addr)
+       {
+               DEBUGMSG("\tcannot map IO - of_iomap\n");
+               return -ENODEV;
+       }
+
+       chip->chip_irq = irq_of_parse_and_map(devnode, 0);
+       if (!chip->chip_irq)
+       {
+               DEBUGMSG("\tcannot map IRQ\n");
+               iounmap(chip->chip_base_addr);
+               return -ENODEV;
+       }
+
+       DEBUGMSG("Bound to io-addr: 0x%08x IRQ: %d\n", (unsigned int)chip->chip_base_addr, chip->chip_irq);
+       
+       return 0;
+}