X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/c6162f4f8d268b7ba1d613459dd1519f587a698e..78bcd4f474077b9c45ba5f8aad2801c93df4fde8:/lincan/src/mpc5200.c diff --git a/lincan/src/mpc5200.c b/lincan/src/mpc5200.c index 10d23a1..2e159cc 100644 --- a/lincan/src/mpc5200.c +++ b/lincan/src/mpc5200.c @@ -38,22 +38,75 @@ #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; +}