/** * @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 #include #include #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; }