Staging: meilhaus: unsigned won't get negative after subtraction
[safe/jmp/linux-2.6] / drivers / staging / meilhaus / mefirmware.c
1 /**
2  * @file mefirmware.c
3  *
4  * @brief Implements the firmware handling.
5  * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
6  * @author Guenter Gebhardt
7  * @author Krzysztof Gantzke    (k.gantzke@meilhaus.de)
8  */
9
10 /***************************************************************************
11  *   Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)     *
12  *   Copyright (C) 2007 by Krzysztof Gantzke k.gantzke@meilhaus.de         *
13  *                                                                         *
14  *   This program is free software; you can redistribute it and/or modify  *
15  *   it under the terms of the GNU General Public License as published by  *
16  *   the Free Software Foundation; either version 2 of the License, or     *
17  *   (at your option) any later version.                                   *
18  *                                                                         *
19  *   This program is distributed in the hope that it will be useful,       *
20  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
21  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
22  *   GNU General Public License for more details.                          *
23  *                                                                         *
24  *   You should have received a copy of the GNU General Public License     *
25  *   along with this program; if not, write to the                         *
26  *   Free Software Foundation, Inc.,                                       *
27  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
28  ***************************************************************************/
29
30 #ifndef __KERNEL__
31 # define __KERNEL__
32 #endif
33
34 #ifndef KBUILD_MODNAME
35 #  define KBUILD_MODNAME KBUILD_STR(mefirmware)
36 #endif
37
38 #include <linux/pci.h>
39 #include <linux/delay.h>
40
41 #include <linux/firmware.h>
42
43 #include "meplx_reg.h"
44 #include "medebug.h"
45
46 #include "mefirmware.h"
47
48 int me_xilinx_download(unsigned long register_base_control,
49                        unsigned long register_base_data,
50                        struct device *dev, const char *firmware_name)
51 {
52         int err = ME_ERRNO_FIRMWARE;
53         uint32_t value = 0;
54         int idx = 0;
55
56         const struct firmware *fw;
57
58         PDEBUG("executed.\n");
59
60         if (!firmware_name) {
61                 PERROR("Request for firmware failed. No name provided. \n");
62                 return err;
63         }
64
65         PINFO("Request '%s' firmware.\n", firmware_name);
66         err = request_firmware(&fw, firmware_name, dev);
67
68         if (err) {
69                 PERROR("Request for firmware failed.\n");
70                 return err;
71         }
72         // Set PLX local interrupt 2 polarity to high.
73         // Interrupt is thrown by init pin of xilinx.
74         outl(PLX_INTCSR_LOCAL_INT2_POL, register_base_control + PLX_INTCSR);
75
76         // Set /CS and /WRITE of the Xilinx
77         value = inl(register_base_control + PLX_ICR);
78         value |= ME_FIRMWARE_CS_WRITE;
79         outl(value, register_base_control + PLX_ICR);
80
81         // Init Xilinx with CS1
82         inl(register_base_data + ME_XILINX_CS1_REG);
83
84         // Wait for init to complete
85         udelay(20);
86
87         // Checkl /INIT pin
88         if (!
89             (inl(register_base_control + PLX_INTCSR) &
90              PLX_INTCSR_LOCAL_INT2_STATE)) {
91                 PERROR("Can't init Xilinx.\n");
92                 release_firmware(fw);
93                 return -EIO;
94         }
95         // Reset /CS and /WRITE of the Xilinx
96         value = inl(register_base_control + PLX_ICR);
97         value &= ~ME_FIRMWARE_CS_WRITE;
98         outl(value, register_base_control + PLX_ICR);
99
100         // Download Xilinx firmware
101         udelay(10);
102
103         for (idx = 0; idx < fw->size; idx++) {
104                 outl(fw->data[idx], register_base_data);
105 #ifdef ME6000_v2_4
106 ///     This checking only for board's version 2.4
107                 // Check if BUSY flag is set (low = ready, high = busy)
108                 if (inl(register_base_control + PLX_ICR) &
109                     ME_FIRMWARE_BUSY_FLAG) {
110                         PERROR("Xilinx is still busy (idx = %d)\n", idx);
111                         release_firmware(fw);
112                         return -EIO;
113                 }
114 #endif //ME6000_v2_4
115         }
116         PDEBUG("Download finished. %d bytes written to PLX.\n", idx);
117
118         // If done flag is high download was successful
119         if (inl(register_base_control + PLX_ICR) & ME_FIRMWARE_DONE_FLAG) {
120                 PDEBUG("SUCCESS. Done flag is set.\n");
121         } else {
122                 PERROR("FAILURE. DONE flag is not set.\n");
123                 release_firmware(fw);
124                 return -EIO;
125         }
126
127         // Set /CS and /WRITE
128         value = inl(register_base_control + PLX_ICR);
129         value |= ME_FIRMWARE_CS_WRITE;
130         outl(value, register_base_control + PLX_ICR);
131
132         PDEBUG("Enable interrupts on the PCI interface.\n");
133         outl(ME_PLX_PCI_ACTIVATE, register_base_control + PLX_INTCSR);
134         release_firmware(fw);
135
136         return 0;
137 }