1 /**************************************************************************/
2 /* File: pc_i03.c - PC-I03 ISA card by IXXAT */
4 /* LinCAN - (Not only) Linux CAN bus driver */
5 /* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz> */
6 /* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz> */
7 /* Funded by OCERA and FRESCOR IST projects */
8 /* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl> */
10 /* LinCAN is free software; you can redistribute it and/or modify it */
11 /* under terms of the GNU General Public License as published by the */
12 /* Free Software Foundation; either version 2, or (at your option) any */
13 /* later version. LinCAN is distributed in the hope that it will be */
14 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
15 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
16 /* General Public License for more details. You should have received a */
17 /* copy of the GNU General Public License along with LinCAN; see file */
18 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
19 /* Cambridge, MA 02139, USA. */
21 /* To allow use of LinCAN in the compact embedded systems firmware */
22 /* and RT-executives (RTEMS for example), main authors agree with next */
23 /* special exception: */
25 /* Including LinCAN header files in a file, instantiating LinCAN generics */
26 /* or templates, or linking other files with LinCAN objects to produce */
27 /* an application image/executable, does not by itself cause the */
28 /* resulting application image/executable to be covered by */
29 /* the GNU General Public License. */
30 /* This exception does not however invalidate any other reasons */
31 /* why the executable file might be covered by the GNU Public License. */
32 /* Publication of enhanced or derived LinCAN files is required although. */
33 /**************************************************************************/
35 #include "../include/can.h"
36 #include "../include/can_sysdep.h"
37 #include "../include/main.h"
38 #include "../include/pc-i03.h"
39 #include "../include/sja1000.h"
41 /* Basic hardware io address. This is also stored in the hardware structure but
42 * we need it global, else we have to change many internal functions.
43 * pc-i03_base_addr is initialized in pc-i03_init_chip_data().
45 unsigned int pci03_base_addr;
48 * IO_RANGE is the io-memory range that gets reserved, please adjust according
49 * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
50 * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
52 #define IO_RANGE 0x200 // The pc-i03 uses an additional 0x100 bytes reset space
55 * pci03_request_io: - reserve io or memory range for can board
56 * @candev: pointer to candevice/board which asks for io. Field @io_addr
57 * of @candev is used in most cases to define start of the range
59 * The function pci03_request_io() is used to reserve the io-memory. If your
60 * hardware uses a dedicated memory range as hardware control registers you
61 * will have to add the code to reserve this memory as well.
62 * %IO_RANGE is the io-memory range that gets reserved, please adjust according
63 * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
64 * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
65 * Return Value: The function returns zero on success or %-ENODEV on failure
68 int pci03_request_io(struct candevice_t *candev)
70 if (!can_request_io_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
71 CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
74 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
80 * pci03_elease_io - free reserved io memory range
81 * @candev: pointer to candevice/board which releases io
83 * The function pci03_release_io() is used to free reserved io-memory.
84 * In case you have reserved more io memory, don't forget to free it here.
85 * IO_RANGE is the io-memory range that gets released, please adjust according
86 * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
87 * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
88 * Return Value: The function always returns zero
91 int pci03_release_io(struct candevice_t *candev)
93 can_release_io_region(candev->io_addr,IO_RANGE);
99 * pci03_reset - hardware reset routine
100 * @candev: Pointer to candevice/board structure
102 * The function pci03_reset() is used to give a hardware reset. This is
103 * rather hardware specific so I haven't included example code. Don't forget to
104 * check the reset status of the chip before returning.
105 * Return Value: The function returns zero on success or %-ENODEV on failure
108 int pci03_reset(struct candevice_t *candev)
112 DEBUGMSG("Resetting pc-i03 hardware ...\n");
113 pci03_write_register(0x01,pci03_base_addr +
114 0x100); // Write arbitrary data to reset mem
117 pci03_write_register(0x00, pci03_base_addr + SJACR);
119 /* Check hardware reset status */
121 while ( (pci03_read_register(pci03_base_addr + SJACR) & sjaCR_RR)
127 CANMSG("Reset status timeout!\n");
128 CANMSG("Please check your hardware.\n");
132 DEBUGMSG("Chip[0] reset status ok.\n");
137 #define RESET_ADDR 0x100
142 * pci03_init_hw_data - Initialize hardware cards
143 * @candev: Pointer to candevice/board structure
145 * The function pci03_init_hw_data() is used to initialize the hardware
146 * structure containing information about the installed CAN-board.
147 * %RESET_ADDR represents the io-address of the hardware reset register.
148 * %NR_82527 represents the number of intel 82527 chips on the board.
149 * %NR_SJA1000 represents the number of philips sja1000 chips on the board.
150 * The flags entry can currently only be %CANDEV_PROGRAMMABLE_IRQ to indicate that
151 * the hardware uses programmable interrupts.
152 * Return Value: The function always returns zero
155 int pci03_init_hw_data(struct candevice_t *candev)
157 candev->res_addr=RESET_ADDR;
158 candev->nr_82527_chips=NR_82527;
159 candev->nr_sja1000_chips=NR_SJA1000;
160 candev->nr_all_chips=NR_82527+NR_SJA1000;
165 * pci03_init_chip_data - Initialize chips
166 * @candev: Pointer to candevice/board structure
167 * @chipnr: Number of the CAN chip on the hardware card
169 * The function pci03_init_chip_data() is used to initialize the hardware
170 * structure containing information about the CAN chips.
171 * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
173 * The @chip_base_addr entry represents the start of the 'official' memory map
174 * of the installed chip. It's likely that this is the same as the @io_addr
175 * argument supplied at module loading time.
176 * The @clock entry holds the chip clock value in Hz.
177 * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
178 * register. Options defined in the %sja1000.h file:
179 * %sjaCDR_CLKOUT_MASK, %sjaCDR_CLK_OFF, %sjaCDR_RXINPEN, %sjaCDR_CBP, %sjaCDR_PELICAN
180 * The entry @sja_ocr_reg holds hardware specific options for the Output Control
181 * register. Options defined in the %sja1000.h file:
182 * %sjaOCR_MODE_BIPHASE, %sjaOCR_MODE_TEST, %sjaOCR_MODE_NORMAL, %sjaOCR_MODE_CLOCK,
183 * %sjaOCR_TX0_LH, %sjaOCR_TX1_ZZ.
184 * The entry @int_clk_reg holds hardware specific options for the Clock Out
185 * register. Options defined in the %i82527.h file:
186 * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
187 * The entry @int_bus_reg holds hardware specific options for the Bus
188 * Configuration register. Options defined in the %i82527.h file:
189 * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
190 * Return Value: The function always returns zero
193 int pci03_init_chip_data(struct candevice_t *candev, int chipnr)
195 sja1000_fill_chipspecops(candev->chip[chipnr]);
196 pci03_base_addr = candev->io_addr;
197 candev->chip[chipnr]->chip_base_addr=candev->io_addr;
198 candev->chip[chipnr]->clock = 16000000;
199 candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
200 candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL |
201 sjaOCR_TX0_HL | sjaOCR_TX1_LZ;
207 * pci03_init_obj_data - Initialize message buffers
208 * @chip: Pointer to chip specific structure
209 * @objnr: Number of the message buffer
211 * The function pci03_init_obj_data() is used to initialize the hardware
212 * structure containing information about the different message objects on the
213 * CAN chip. In case of the sja1000 there's only one message object but on the
214 * i82527 chip there are 15.
215 * The code below is for a i82527 chip and initializes the object base addresses
216 * The entry @obj_base_addr represents the first memory address of the message
217 * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
219 * Unless the hardware uses a segmented memory map, flags can be set zero.
220 * Return Value: The function always returns zero
223 int pci03_init_obj_data(struct canchip_t *chip, int objnr)
225 chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
231 * pci03_program_irq - program interrupts
232 * @candev: Pointer to candevice/board structure
234 * The function pci03_program_irq() is used for hardware that uses
235 * programmable interrupts. If your hardware doesn't use programmable interrupts
236 * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and
237 * leave this function unedited. Again this function is hardware specific so
238 * there's no example code.
239 * Return value: The function returns zero on success or %-ENODEV on failure
242 int pci03_program_irq(struct candevice_t *candev)
248 * pci03_write_register - Low level write register routine
249 * @data: data to be written
250 * @address: memory address to write to
252 * The function pci03_write_register() is used to write to hardware registers
253 * on the CAN chip. You should only have to edit this function if your hardware
254 * uses some specific write process.
255 * Return Value: The function does not return a value
258 void pci03_write_register(unsigned data, can_ioptr_t address)
260 unsigned int *pci03_base_ptr;
261 unsigned short address_to_write;
263 /* The read/write functions are called by an extra abstract function.
264 * This extra function adds the basic io address of the card to the
265 * memory address we want to write to, so we substract the basic io
266 * address again to obtain the offset into the hardware's memory map.
268 address_to_write = address - pci03_base_addr; // Offset
269 pci03_base_ptr = (unsigned int *)(pci03_base_addr * 0x100001);
270 (*(pci03_base_ptr+address_to_write)) = data;
274 * pci03_read_register - Low level read register routine
275 * @address: memory address to read from
277 * The function pci03_read_register() is used to read from hardware registers
278 * on the CAN chip. You should only have to edit this function if your hardware
279 * uses some specific read process.
280 * Return Value: The function returns the value stored in @address
283 unsigned pci03_read_register(can_ioptr_t address)
285 unsigned int *pci03_base_ptr;
286 unsigned short address_to_read;
288 /* The read/write functions are called by an extra abstract function.
289 * This extra function adds the basic io address of the card to the
290 * memory address we want to write to, so we substract the basic io
291 * address again to obtain the offset into the hardware's memory map.
293 address_to_read = address - pci03_base_addr;
294 pci03_base_ptr = (unsigned int *)(pci03_base_addr * 0x100001);
295 return (*(pci03_base_ptr+address_to_read));
298 int pci03_register(struct hwspecops_t *hwspecops)
300 hwspecops->request_io = pci03_request_io;
301 hwspecops->release_io = pci03_release_io;
302 hwspecops->reset = pci03_reset;
303 hwspecops->init_hw_data = pci03_init_hw_data;
304 hwspecops->init_chip_data = pci03_init_chip_data;
305 hwspecops->init_obj_data = pci03_init_obj_data;
306 hwspecops->write_register = pci03_write_register;
307 hwspecops->read_register = pci03_read_register;
308 hwspecops->program_irq = pci03_program_irq;