X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/4ee1fa3f095f7da94c8996d3f499273ff84c9023..b18e586453cf962a4032890f34d05a9fd362cf02:/lincan/src/mpc5200.c diff --git a/lincan/src/mpc5200.c b/lincan/src/mpc5200.c new file mode 100644 index 0000000..10d23a1 --- /dev/null +++ b/lincan/src/mpc5200.c @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* File: mpc5200.c - Freescale MPC5200 MSCAN controller support */ +/* */ +/* LinCAN - (Not only) Linux CAN bus driver */ +/* Copyright (C) 2002-2009 DCE FEE CTU Prague */ +/* Copyright (C) 2002-2009 Pavel Pisa */ +/* Copyright (C) 2007-2008 Martin Petera */ +/* Funded by OCERA and FRESCOR IST projects */ +/* Based on CAN driver code by Arnaud Westenberg */ +/* */ +/* LinCAN is free software; you can redistribute it and/or modify it */ +/* under terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2, or (at your option) any */ +/* later version. LinCAN is distributed in the hope that it will be */ +/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */ +/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. You should have received a */ +/* copy of the GNU General Public License along with LinCAN; see file */ +/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/* */ +/* To allow use of LinCAN in the compact embedded systems firmware */ +/* and RT-executives (RTEMS for example), main authors agree with next */ +/* special exception: */ +/* */ +/* Including LinCAN header files in a file, instantiating LinCAN generics */ +/* or templates, or linking other files with LinCAN objects to produce */ +/* an application image/executable, does not by itself cause the */ +/* resulting application image/executable to be covered by */ +/* the GNU General Public License. */ +/* This exception does not however invalidate any other reasons */ +/* why the executable file might be covered by the GNU Public License. */ +/* Publication of enhanced or derived LinCAN files is required although. */ +/**************************************************************************/ + +#include "../include/can.h" +#include "../include/can_sysdep.h" +#include "../include/main.h" +#include "../include/mpc5200.h" +#include "../include/mscan.h" + +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; + } + + DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + candev->nr_all_chips * IO_RANGE - 1); + return 0; +} + +int mpc5200_release_io(struct candevice_t *candev) +{ + can_release_io_region(candev->io_addr, candev->nr_all_chips * IO_RANGE); + + return 0; +} + +int mpc5200_reset(struct candevice_t *candev) +{ + 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; + } + + return 0; +} + +int mpc5200_init_hw_data(struct candevice_t *candev) +{ + /* candev->res_addr = RESET_ADDR; */ + candev->nr_82527_chips = NR_82527; + candev->nr_sja1000_chips = NR_SJA1000; + candev->nr_all_chips = NR_ALL; + /* candev->flags |= CANDEV_PROGRAMMABLE_IRQ; */ + + 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; + + return 0; +} + +int mpc5200_init_obj_data(struct canchip_t *chip, int objnr) +{ + /* we have only two chips with only one mailbox each */ + chip->msgobj[objnr]->obj_base_addr = (can_ioptr_t) MSCAN_CTL0 + MPC5200_CAN_CHIP_OFFSET * objnr; + + return 0; +} + +int mpc5200_program_irq(struct candevice_t *candev) +{ + /* we don't use programmable interrupt on MPC5200 */ + return 0; +} + + +void mpc5200_write_register(unsigned data, can_ioptr_t address) +{ + /* address is an absolute address */ + 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"); + return readb(address); /* regs in PowerPC (5200) are one-byte length */ +} + +int mpc5200_register(struct hwspecops_t *hwspecops) +{ + hwspecops->request_io = mpc5200_request_io; + hwspecops->release_io = mpc5200_release_io; + hwspecops->reset = mpc5200_reset; + 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->write_register = mpc5200_write_register; + hwspecops->read_register = mpc5200_read_register; + return 0; +}