![David Kiliani](/assets/img/avatar_default.png)
Originally written by Guenter Gebhardt <g.gebhardt@meilhaus.de> and Krzysztof Gantzke <k.gantzke@meilhaus.de> This is the drv/lnx/mod directory of ME-IDS 1.2.9 tarball with some files from drv/lnx/include. Signed-off-by: David Kiliani <mail@davidkiliani.de> Cc: Guenter Gebhardt <g.gebhardt@meilhaus.de> Cc: Krzysztof Gantzke <k.gantzke@meilhaus.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
138 lines
4.3 KiB
C
138 lines
4.3 KiB
C
/**
|
|
* @file mefirmware.c
|
|
*
|
|
* @brief Implements the firmware handling.
|
|
* @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
|
|
* @author Guenter Gebhardt
|
|
* @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
|
|
*/
|
|
|
|
/***************************************************************************
|
|
* Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) *
|
|
* Copyright (C) 2007 by Krzysztof Gantzke k.gantzke@meilhaus.de *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program 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 this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
***************************************************************************/
|
|
|
|
#ifndef __KERNEL__
|
|
# define __KERNEL__
|
|
#endif
|
|
|
|
#ifndef KBUILD_MODNAME
|
|
# define KBUILD_MODNAME KBUILD_STR(mefirmware)
|
|
#endif
|
|
|
|
#include <linux/pci.h>
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/firmware.h>
|
|
|
|
#include "meplx_reg.h"
|
|
#include "medebug.h"
|
|
|
|
#include "mefirmware.h"
|
|
|
|
int me_xilinx_download(unsigned long register_base_control,
|
|
unsigned long register_base_data,
|
|
struct device *dev, const char *firmware_name)
|
|
{
|
|
int err = ME_ERRNO_FIRMWARE;
|
|
uint32_t value = 0;
|
|
int idx = 0;
|
|
|
|
const struct firmware *fw;
|
|
|
|
PDEBUG("executed.\n");
|
|
|
|
if (!firmware_name) {
|
|
PERROR("Request for firmware failed. No name provided. \n");
|
|
return err;
|
|
}
|
|
|
|
PINFO("Request '%s' firmware.\n", firmware_name);
|
|
err = request_firmware(&fw, firmware_name, dev);
|
|
|
|
if (err) {
|
|
PERROR("Request for firmware failed.\n");
|
|
return err;
|
|
}
|
|
// Set PLX local interrupt 2 polarity to high.
|
|
// Interrupt is thrown by init pin of xilinx.
|
|
outl(PLX_INTCSR_LOCAL_INT2_POL, register_base_control + PLX_INTCSR);
|
|
|
|
// Set /CS and /WRITE of the Xilinx
|
|
value = inl(register_base_control + PLX_ICR);
|
|
value |= ME_FIRMWARE_CS_WRITE;
|
|
outl(value, register_base_control + PLX_ICR);
|
|
|
|
// Init Xilinx with CS1
|
|
inl(register_base_data + ME_XILINX_CS1_REG);
|
|
|
|
// Wait for init to complete
|
|
udelay(20);
|
|
|
|
// Checkl /INIT pin
|
|
if (!
|
|
(inl(register_base_control + PLX_INTCSR) &
|
|
PLX_INTCSR_LOCAL_INT2_STATE)) {
|
|
PERROR("Can't init Xilinx.\n");
|
|
release_firmware(fw);
|
|
return -EIO;
|
|
}
|
|
// Reset /CS and /WRITE of the Xilinx
|
|
value = inl(register_base_control + PLX_ICR);
|
|
value &= ~ME_FIRMWARE_CS_WRITE;
|
|
outl(value, register_base_control + PLX_ICR);
|
|
|
|
// Download Xilinx firmware
|
|
udelay(10);
|
|
|
|
for (idx = 0; idx < fw->size; idx++) {
|
|
outl(fw->data[idx], register_base_data);
|
|
#ifdef ME6000_v2_4
|
|
/// This checking only for board's version 2.4
|
|
// Check if BUSY flag is set (low = ready, high = busy)
|
|
if (inl(register_base_control + PLX_ICR) &
|
|
ME_FIRMWARE_BUSY_FLAG) {
|
|
PERROR("Xilinx is still busy (idx = %d)\n", idx);
|
|
release_firmware(fw);
|
|
return -EIO;
|
|
}
|
|
#endif //ME6000_v2_4
|
|
}
|
|
PDEBUG("Download finished. %d bytes written to PLX.\n", idx);
|
|
|
|
// If done flag is high download was successful
|
|
if (inl(register_base_control + PLX_ICR) & ME_FIRMWARE_DONE_FLAG) {
|
|
PDEBUG("SUCCESS. Done flag is set.\n");
|
|
} else {
|
|
PERROR("FAILURE. DONE flag is not set.\n");
|
|
release_firmware(fw);
|
|
return -EIO;
|
|
}
|
|
|
|
// Set /CS and /WRITE
|
|
value = inl(register_base_control + PLX_ICR);
|
|
value |= ME_FIRMWARE_CS_WRITE;
|
|
outl(value, register_base_control + PLX_ICR);
|
|
|
|
PDEBUG("Enable interrupts on the PCI interface.\n");
|
|
outl(ME_PLX_PCI_ACTIVATE, register_base_control + PLX_INTCSR);
|
|
release_firmware(fw);
|
|
|
|
return 0;
|
|
}
|