X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/b18e586453cf962a4032890f34d05a9fd362cf02..04ac67cc3cac14cd601daacd0592121ec0b84012:/lincan/src/mpc5200.c diff --git a/lincan/src/mpc5200.c b/lincan/src/mpc5200.c index 10d23a1..ae0a465 100644 --- a/lincan/src/mpc5200.c +++ b/lincan/src/mpc5200.c @@ -38,40 +38,96 @@ #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]); + + kfree(chips_addr); return 0; } int mpc5200_reset(struct candevice_t *candev) { - int i; + int i; DEBUGMSG("Resetting MSCAN chips ...\n"); 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; } -int mpc5200_init_hw_data(struct candevice_t *candev) +int mpc5200_init_hw_data(struct candevice_t *candev) { /* candev->res_addr = RESET_ADDR; */ candev->nr_82527_chips = NR_82527; @@ -81,15 +137,32 @@ int mpc5200_init_hw_data(struct candevice_t *candev) return 0; } + +/* special function for midam board */ +int mpc5200_midam_init_hw_data(struct candevice_t *candev) +{ + /* use same init routine */ + mpc5200_init_hw_data(candev); + + /* modify chip count */ + candev->nr_all_chips = NR_ALL_MIDAM; + + return 0; +} + 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; } @@ -103,7 +176,7 @@ int mpc5200_init_obj_data(struct canchip_t *chip, int objnr) int mpc5200_program_irq(struct candevice_t *candev) { - /* we don't use programmable interrupt on MPC5200 */ + /* we don't use programmable interrupt on MPC5200 */ return 0; } @@ -111,14 +184,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 +203,41 @@ 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_midam_register(struct hwspecops_t *hwspecops) +{ + /* use same register routine for MIDAM board */ + mpc5200_register(hwspecops); + + /* use specific init_hw_data */ + hwspecops->init_hw_data = mpc5200_midam_init_hw_data; + + 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; +}