+/* oscar.c
+ * Linux CAN-bus device driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3 17 Jun 2004
+
+ NOTE: Please see the template.c file for the comments relating to this code.
+ Herein is the modified copy of the functions
+
+ */
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
+#include "../include/main.h"
+#include "../include/oscar.h"
+#include "../include/i82527.h"
+#include "../include/sja1000.h"
+
+#define IO_RANGE 0x80 // allow both basic CAN and PeliCAN modes for sja1000
+
+int oscar_request_io(struct candevice_t *candev)
+{
+ if (!can_request_io_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
+ CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
+ return -ENODEV;
+ }else {
+ DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
+ }
+ return 0;
+}
+
+int oscar_release_io(struct candevice_t *candev)
+{
+ can_release_io_region(candev->io_addr,IO_RANGE);
+
+ return 0;
+}
+
+int oscar_reset(struct candevice_t *candev)
+{
+ DEBUGMSG("Cannot issue a hardware reset to the CAN chip.");
+ return -ENODEV;
+}
+
+int oscar_init_hw_data(struct candevice_t *candev)
+{
+ candev->res_addr = 0x0; // RESET address?
+ candev->nr_82527_chips = 0;
+ candev->nr_sja1000_chips = 1; // We've got a SJA1000 variant
+ candev->nr_all_chips= 1;
+ candev->flags |= CANDEV_PROGRAMMABLE_IRQ;
+
+ return 0;
+}
+
+int oscar_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+ // i82527_fill_chipspecops(candev->chip[chipnr]);
+ sja1000_fill_chipspecops(candev->chip[chipnr]);
+ // sja1000p_fill_chipspecops(candev->chip[chipnr]);
+
+ candev->chip[chipnr]->chip_base_addr = candev->io_addr;
+ candev->chip[chipnr]->clock = 12000000;
+ candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP; // we use an external tranceiver
+ candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL | sjaOCR_TX0_LH;
+ // these three int_ registers are unused (we don't have this chip)
+ candev->chip[chipnr]->int_cpu_reg = 0;
+ candev->chip[chipnr]->int_clk_reg = 0;
+ candev->chip[chipnr]->int_bus_reg = 0;
+
+ return 0;
+}
+
+int oscar_init_obj_data(struct canchip_t *chip, int objnr)
+{
+ chip->msgobj[objnr]->obj_base_addr = chip->chip_base_addr;
+
+ return 0;
+}
+
+int oscar_program_irq(struct candevice_t *candev)
+{
+ // CAN_IRQ_L (active low) interrupt: PF2 / INT2 on our LH7A400 SoC
+ // This IRQ is set up already by the kernel.
+
+ return 0;
+}
+
+void oscar_write_register(unsigned data, unsigned long address)
+{
+ outb(data,address);
+}
+
+unsigned oscar_read_register(unsigned long address)
+{
+ return inb(address);
+}
+
+/* !!! Don't change this function !!! */
+int oscar_register(struct hwspecops_t *hwspecops)
+{
+ hwspecops->request_io = oscar_request_io;
+ hwspecops->release_io = oscar_release_io;
+ hwspecops->reset = oscar_reset;
+ hwspecops->init_hw_data = oscar_init_hw_data;
+ hwspecops->init_chip_data = oscar_init_chip_data;
+ hwspecops->init_obj_data = oscar_init_obj_data;
+ hwspecops->write_register = oscar_write_register;
+ hwspecops->read_register = oscar_read_register;
+ hwspecops->program_irq = oscar_program_irq;
+ return 0;
+}