]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/app/usbcan/ul_usb1.c
embedded: reintroduce missing emulated bus initialization for UL_USB1 board.
[lincan.git] / embedded / app / usbcan / ul_usb1.c
1 /**************************************************************************/
2 /* File: ul_usb1.c - UL_USB1 board specific part of USB<->CAN converter   */
3 /*                                                                        */
4 /* LinCAN - (Not only) Linux CAN bus driver                               */
5 /* Copyright (C) 2002-2011 DCE FEE CTU Prague <http://dce.felk.cvut.cz>   */
6 /* Copyright (C) 2008 Jan Kriz email:johen@post.cz                        */
7 /*                                                                        */
8 /* LinCAN is free software; you can redistribute it and/or modify it      */
9 /* under terms of the GNU General Public License as published by the      */
10 /* Free Software Foundation; either version 2, or (at your option) any    */
11 /* later version.  LinCAN is distributed in the hope that it will be      */
12 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
13 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
14 /* General Public License for more details. You should have received a    */
15 /* copy of the GNU General Public License along with LinCAN; see file     */
16 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
17 /* Cambridge, MA 02139, USA.                                              */
18 /*                                                                        */
19 /* To allow use of LinCAN in the compact embedded systems firmware        */
20 /* and RT-executives (RTEMS for example), main authors agree with next    */
21 /* special exception:                                                     */
22 /*                                                                        */
23 /* Including LinCAN header files in a file, instantiating LinCAN generics */
24 /* or templates, or linking other files with LinCAN objects to produce    */
25 /* an application image/executable, does not by itself cause the          */
26 /* resulting application image/executable to be covered by                */
27 /* the GNU General Public License.                                        */
28 /* This exception does not however invalidate any other reasons           */
29 /* why the executable file might be covered by the GNU Public License.    */
30 /* Publication of enhanced or derived LinCAN files is required although.  */
31 /**************************************************************************/
32
33 #include "./can/can.h"
34 #include "./can/can_sysdep.h"
35 #include "./can/main.h"
36 #include "./can/devcommon.h"
37 #include "./can/setup.h"
38 // #include "./can/finish.h"
39 #include "./can/i82527.h"
40 //#include "../include/sja1000.h"
41 #include "./can/sja1000p.h"
42
43 #include "./can/errno.h"
44
45 #include "./can/ul_usb1.h"
46
47 /* Get a minor range for your devices from the usb maintainer */
48 #define USB_SKEL_MINOR_BASE     192
49
50 #define CAN_OP_MASK 0x80
51 #define CAN_OP_READ 0x80
52 #define CAN_OP_WRITE 0x00
53
54
55         /* our private defines. if this grows any larger, use your own .h file */
56 #define MAX_TRANSFER            (PAGE_SIZE - 512)
57 /* MAX_TRANSFER is chosen so that the VM is not stressed by
58    allocations > PAGE_SIZE and the number of packets in a page
59    is an integer 512 is the largest possible packet on EHCI */
60 #define WRITES_IN_FLIGHT        8
61 /* arbitrarily chosen */
62
63 /* Define these values to match your devices */
64 #define USB_SKEL_VENDOR_ID      0xDEAD
65 #define USB_SKEL_PRODUCT_ID     0x1001
66
67
68 /*
69  * IO_RANGE is the io-memory range that gets reserved, please adjust according
70  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
71  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
72  */
73 #define IO_RANGE 0x100
74
75 /** ul_usb1_request_io
76  * ul_usb1_request_io: - reserve io or memory range for can board
77  * @candev: pointer to candevice/board which asks for io. Field @io_addr
78  *      of @candev is used in most cases to define start of the range
79  *
80  * The function ul_usb1_request_io() is used to reserve the io-memory. If your
81  * hardware uses a dedicated memory range as hardware control registers you
82  * will have to add the code to reserve this memory as well.
83  * %IO_RANGE is the io-memory range that gets reserved, please adjust according
84  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
85  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
86  * Return Value: The function returns zero on success or %-ENODEV on failure
87  * File: src/ul_usb1.c
88  */
89 int ul_usb1_request_io(struct candevice_t *candev)
90 {
91         return 0;
92 }
93
94 /** ul_usb1_release_io
95  * ul_usb1_release_io - free reserved io memory range
96  * @candev: pointer to candevice/board which releases io
97  *
98  * The function ul_usb1_release_io() is used to free reserved io-memory.
99  * In case you have reserved more io memory, don't forget to free it here.
100  * IO_RANGE is the io-memory range that gets released, please adjust according
101  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
102  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
103  * Return Value: The function always returns zero
104  * File: src/ul_usb1.c
105  */
106 int ul_usb1_release_io(struct candevice_t *candev)
107 {
108         return 0;
109 }
110
111 /** ul_usb1_reset
112  * ul_usb1_reset - hardware reset routine
113  * @candev: Pointer to candevice/board structure
114  *
115  * The function ul_usb1_reset() is used to give a hardware reset. This is
116  * rather hardware specific so I haven't included example code. Don't forget to
117  * check the reset status of the chip before returning.
118  * Return Value: The function returns zero on success or %-ENODEV on failure
119  * File: src/ul_usb1.c
120  */
121 int ul_usb1_reset(struct candevice_t *candev)
122 {
123         return can_init();
124 }
125
126 #define RESET_ADDR 0x0
127 #define NR_82527 0
128 #define NR_SJA1000 1
129
130 /** ul_usb1_init_hw_data
131  * ul_usb1_init_hw_data - Initialize hardware cards
132  * @candev: Pointer to candevice/board structure
133  *
134  * The function ul_usb1_init_hw_data() is used to initialize the hardware
135  * structure containing information about the installed CAN-board.
136  * %RESET_ADDR represents the io-address of the hardware reset register.
137  * %NR_82527 represents the number of Intel 82527 chips on the board.
138  * %NR_SJA1000 represents the number of Philips sja1000 chips on the board.
139  * The flags entry can currently only be %CANDEV_PROGRAMMABLE_IRQ to indicate that
140  * the hardware uses programmable interrupts.
141  * Return Value: The function always returns zero
142  * File: src/ul_usb1.c
143  */
144 int ul_usb1_init_hw_data(struct candevice_t *candev)
145 {
146         candev->res_addr=RESET_ADDR;
147         candev->nr_82527_chips=NR_82527;
148         candev->nr_sja1000_chips=NR_SJA1000;
149         candev->nr_all_chips=NR_82527+NR_SJA1000;
150         candev->flags |= CANDEV_PROGRAMMABLE_IRQ*0;
151
152         return 0;
153 }
154
155 /** ul_usb1_init_chip_data
156  * ul_usb1_init_chip_data - Initialize chips
157  * @candev: Pointer to candevice/board structure
158  * @chipnr: Number of the CAN chip on the hardware card
159  *
160  * The function ul_usb1_init_chip_data() is used to initialize the hardware
161  * structure containing information about the CAN chips.
162  * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
163  * "sja1000".
164  * The @chip_base_addr entry represents the start of the 'official' memory map
165  * of the installed chip. It's likely that this is the same as the @io_addr
166  * argument supplied at module loading time.
167  * The @clock entry holds the chip clock value in Hz.
168  * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
169  * register. Options defined in the %sja1000.h file:
170  * %sjaCDR_CLKOUT_MASK, %sjaCDR_CLK_OFF, %sjaCDR_RXINPEN, %sjaCDR_CBP, %sjaCDR_PELICAN
171  * The entry @sja_ocr_reg holds hardware specific options for the Output Control
172  * register. Options defined in the %sja1000.h file:
173  * %sjaOCR_MODE_BIPHASE, %sjaOCR_MODE_TEST, %sjaOCR_MODE_NORMAL, %sjaOCR_MODE_CLOCK,
174  * %sjaOCR_TX0_LH, %sjaOCR_TX1_ZZ.
175  * The entry @int_clk_reg holds hardware specific options for the Clock Out
176  * register. Options defined in the %i82527.h file:
177  * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
178  * The entry @int_bus_reg holds hardware specific options for the Bus
179  * Configuration register. Options defined in the %i82527.h file:
180  * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
181  * The entry @int_cpu_reg holds hardware specific options for the cpu interface
182  * register. Options defined in the %i82527.h file:
183  * %iCPU_CEN, %iCPU_MUX, %iCPU_SLP, %iCPU_PWD, %iCPU_DMC, %iCPU_DSC, %iCPU_RST.
184  * Return Value: The function always returns zero
185  * File: src/ul_usb1.c
186  */
187 int ul_usb1_init_chip_data(struct candevice_t *candev, int chipnr)
188 {
189         /*i82527_fill_chipspecops(candev->chip[chipnr]);*/
190         /*sja1000_fill_chipspecops(candev->chip[chipnr]);*/
191         sja1000p_fill_chipspecops(candev->chip[chipnr]);
192
193         candev->chip[chipnr]->flags|= CHIP_IRQ_CUSTOM;
194
195         candev->chip[chipnr]->chip_base_addr=0;
196         candev->chip[chipnr]->clock = 24000000;
197         candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
198         candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
199         candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
200         candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
201         candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL |
202                                                                 sjaOCR_TX0_LH;
203
204         candev->chip[chipnr]->chip_data=(void *)malloc(sizeof(struct ul_usb1_chip_data));
205         if (candev->chip[chipnr]->chip_data==NULL)
206                 return -ENOMEM;
207         return 0;
208 }
209
210 /** ul_usb1_init_obj_data
211  * ul_usb1_init_obj_data - Initialize message buffers
212  * @chip: Pointer to chip specific structure
213  * @objnr: Number of the message buffer
214  *
215  * The function ul_usb1_init_obj_data() is used to initialize the hardware
216  * structure containing information about the different message objects on the
217  * CAN chip. In case of the sja1000 there's only one message object but on the
218  * i82527 chip there are 15.
219  * The code below is for a i82527 chip and initializes the object base addresses
220  * The entry @obj_base_addr represents the first memory address of the message
221  * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
222  * base address.
223  * Unless the hardware uses a segmented memory map, flags can be set zero.
224  * Return Value: The function always returns zero
225  * File: src/ul_usb1.c
226  */
227 int ul_usb1_init_obj_data(struct canchip_t *chip, int objnr)
228 {
229         chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
230
231         return 0;
232 }
233
234 /** ul_usb1_program_irq
235  * ul_usb1_program_irq - program interrupts
236  * @candev: Pointer to candevice/board structure
237  *
238  * The function ul_usb1_program_irq() is used for hardware that uses
239  * programmable interrupts. If your hardware doesn't use programmable interrupts
240  * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and
241  * leave this function unedited. Again this function is hardware specific so
242  * there's no example code.
243  * Return value: The function returns zero on success or %-ENODEV on failure
244  * File: src/ul_usb1.c
245  */
246 int ul_usb1_program_irq(struct candevice_t *candev)
247 {
248         return 0;
249 }
250
251 /** ul_usb1_write_register
252  * ul_usb1_write_register - Low level write register routine
253  * @data: data to be written
254  * @address: memory address to write to
255  *
256  * The function ul_usb1_write_register() is used to write to hardware registers
257  * on the CAN chip. You should only have to edit this function if your hardware
258  * uses some specific write process.
259  * Return Value: The function does not return a value
260  * File: src/ul_usb1.c
261  */
262 void ul_usb1_write_register(unsigned data, unsigned long address)
263 {
264         can_write(data, address & 0xFF);
265 }
266
267 /** ul_usb1_read_register
268  * ul_usb1_read_register - Low level read register routine
269  * @address: memory address to read from
270  *
271  * The function ul_usb1_read_register() is used to read from hardware registers
272  * on the CAN chip. You should only have to edit this function if your hardware
273  * uses some specific read process.
274  * Return Value: The function returns the value stored in @address
275  * File: src/ul_usb1.c
276  */
277 unsigned ul_usb1_read_register(unsigned long address)
278 {
279         uint8_t data;
280         data = can_read(address & 0xFF);
281         return data;
282 }
283
284 /* !!! Don't change this function !!! */
285 int ul_usb1_register(struct hwspecops_t *hwspecops)
286 {
287         hwspecops->request_io = ul_usb1_request_io;
288         hwspecops->release_io = ul_usb1_release_io;
289         hwspecops->reset = ul_usb1_reset;
290         hwspecops->init_hw_data = ul_usb1_init_hw_data;
291         hwspecops->init_chip_data = ul_usb1_init_chip_data;
292         hwspecops->init_obj_data = ul_usb1_init_obj_data;
293         hwspecops->write_register = ul_usb1_write_register;
294         hwspecops->read_register = ul_usb1_read_register;
295         hwspecops->program_irq = ul_usb1_program_irq;
296         return 0;
297 }
298