Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  1/******************************************************************************
  2 *
  3 * GPL LICENSE SUMMARY
  4 *
  5 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of version 2 of the GNU General Public License as
  9 * published by the Free Software Foundation.
 10 *
 11 * This program is distributed in the hope that it will be useful, but
 12 * WITHOUT ANY WARRANTY; without even the implied warranty of
 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14 * General Public License for more details.
 15 *
 16 * You should have received a copy of the GNU General Public License
 17 * along with this program; if not, write to the Free Software
 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
 19 * USA
 20 *
 21 * The full GNU General Public License is included in this distribution
 22 * in the file called LICENSE.GPL.
 23 *
 24 * Contact Information:
 25 *  Intel Linux Wireless <ilw@linux.intel.com>
 26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 27 *
 28 *****************************************************************************/
 29
 30#include <linux/kernel.h>
 31#include <linux/module.h>
 32#include <linux/init.h>
 33#include <linux/sched.h>
 34
 35#include "iwl-dev.h"
 36#include "iwl-core.h"
 37#include "iwl-io.h"
 38#include "iwl-helpers.h"
 39#include "iwl-4965-hw.h"
 40#include "iwl-4965.h"
 41#include "iwl-4965-calib.h"
 42
 43#define IWL_AC_UNSET -1
 44
 45/**
 46 * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
 47 *   using sample data 100 bytes apart.  If these sample points are good,
 48 *   it's a pretty good bet that everything between them is good, too.
 49 */
 50static int
 51iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
 52{
 53	u32 val;
 54	int ret = 0;
 55	u32 errcnt = 0;
 56	u32 i;
 57
 58	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
 59
 60	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
 61		/* read data comes through single port, auto-incr addr */
 62		/* NOTE: Use the debugless read so we don't flood kernel log
 63		 * if IWL_DL_IO is set */
 64		iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
 65			i + IWL4965_RTC_INST_LOWER_BOUND);
 66		val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
 67		if (val != le32_to_cpu(*image)) {
 68			ret = -EIO;
 69			errcnt++;
 70			if (errcnt >= 3)
 71				break;
 72		}
 73	}
 74
 75	return ret;
 76}
 77
 78/**
 79 * iwl4965_verify_inst_full - verify runtime uCode image in card vs. host,
 80 *     looking at all data.
 81 */
 82static int iwl4965_verify_inst_full(struct iwl_priv *priv, __le32 *image,
 83				 u32 len)
 84{
 85	u32 val;
 86	u32 save_len = len;
 87	int ret = 0;
 88	u32 errcnt;
 89
 90	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
 91
 92	iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
 93			   IWL4965_RTC_INST_LOWER_BOUND);
 94
 95	errcnt = 0;
 96	for (; len > 0; len -= sizeof(u32), image++) {
 97		/* read data comes through single port, auto-incr addr */
 98		/* NOTE: Use the debugless read so we don't flood kernel log
 99		 * if IWL_DL_IO is set */
100		val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
101		if (val != le32_to_cpu(*image)) {
102			IWL_ERR(priv, "uCode INST section is invalid at "
103				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
104				  save_len - len, val, le32_to_cpu(*image));
105			ret = -EIO;
106			errcnt++;
107			if (errcnt >= 20)
108				break;
109		}
110	}
111
112	if (!errcnt)
113		IWL_DEBUG_INFO(priv,
114		    "ucode image in INSTRUCTION memory is good\n");
115
116	return ret;
117}
118
119/**
120 * iwl4965_verify_ucode - determine which instruction image is in SRAM,
121 *    and verify its contents
122 */
123int iwl4965_verify_ucode(struct iwl_priv *priv)
124{
125	__le32 *image;
126	u32 len;
127	int ret;
128
129	/* Try bootstrap */
130	image = (__le32 *)priv->ucode_boot.v_addr;
131	len = priv->ucode_boot.len;
132	ret = iwl4965_verify_inst_sparse(priv, image, len);
133	if (!ret) {
134		IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n");
135		return 0;
136	}
137
138	/* Try initialize */
139	image = (__le32 *)priv->ucode_init.v_addr;
140	len = priv->ucode_init.len;
141	ret = iwl4965_verify_inst_sparse(priv, image, len);
142	if (!ret) {
143		IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n");
144		return 0;
145	}
146
147	/* Try runtime/protocol */
148	image = (__le32 *)priv->ucode_code.v_addr;
149	len = priv->ucode_code.len;
150	ret = iwl4965_verify_inst_sparse(priv, image, len);
151	if (!ret) {
152		IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
153		return 0;
154	}
155
156	IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
157
158	/* Since nothing seems to match, show first several data entries in
159	 * instruction SRAM, so maybe visual inspection will give a clue.
160	 * Selection of bootstrap image (vs. other images) is arbitrary. */
161	image = (__le32 *)priv->ucode_boot.v_addr;
162	len = priv->ucode_boot.len;
163	ret = iwl4965_verify_inst_full(priv, image, len);
164
165	return ret;
166}