brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · b8ed193 Raw
223 lines · c
1/*2 * Atheros CARL9170 driver3 *4 * Basic HW register/memory/command access functions5 *6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>7 *8 * This program is free software; you can redistribute it and/or modify9 * it under the terms of the GNU General Public License as published by10 * the Free Software Foundation; either version 2 of the License, or11 * (at your option) any later version.12 *13 * This program is distributed in the hope that it will be useful,14 * but WITHOUT ANY WARRANTY; without even the implied warranty of15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the16 * GNU General Public License for more details.17 *18 * You should have received a copy of the GNU General Public License19 * along with this program; see the file COPYING.  If not, see20 * http://www.gnu.org/licenses/.21 *22 * This file incorporates work covered by the following copyright and23 * permission notice:24 *    Copyright (c) 2007-2008 Atheros Communications, Inc.25 *26 *    Permission to use, copy, modify, and/or distribute this software for any27 *    purpose with or without fee is hereby granted, provided that the above28 *    copyright notice and this permission notice appear in all copies.29 *30 *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES31 *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF32 *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR33 *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES34 *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN35 *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF36 *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.37 */38 39#include <asm/div64.h>40#include "carl9170.h"41#include "cmd.h"42 43int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)44{45	const __le32 buf[2] = {46		cpu_to_le32(reg),47		cpu_to_le32(val),48	};49	int err;50 51	err = carl9170_exec_cmd(ar, CARL9170_CMD_WREG, sizeof(buf),52				(u8 *) buf, 0, NULL);53	if (err) {54		if (net_ratelimit()) {55			wiphy_err(ar->hw->wiphy, "writing reg %#x "56				"(val %#x) failed (%d)\n", reg, val, err);57		}58	}59	return err;60}61 62int carl9170_read_mreg(struct ar9170 *ar, const int nregs,63		       const u32 *regs, u32 *out)64{65	int i, err;66	__le32 *offs, *res;67 68	/* abuse "out" for the register offsets, must be same length */69	offs = (__le32 *)out;70	for (i = 0; i < nregs; i++)71		offs[i] = cpu_to_le32(regs[i]);72 73	/* also use the same buffer for the input */74	res = (__le32 *)out;75 76	err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,77				4 * nregs, (u8 *)offs,78				4 * nregs, (u8 *)res);79	if (err) {80		if (net_ratelimit()) {81			wiphy_err(ar->hw->wiphy, "reading regs failed (%d)\n",82				  err);83		}84		return err;85	}86 87	/* convert result to cpu endian */88	for (i = 0; i < nregs; i++)89		out[i] = le32_to_cpu(res[i]);90 91	return 0;92}93 94int carl9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val)95{96	return carl9170_read_mreg(ar, 1, &reg, val);97}98 99int carl9170_echo_test(struct ar9170 *ar, const u32 v)100{101	u32 echores;102	int err;103 104	err = carl9170_exec_cmd(ar, CARL9170_CMD_ECHO,105				4, (u8 *)&v,106				4, (u8 *)&echores);107	if (err)108		return err;109 110	if (v != echores) {111		wiphy_info(ar->hw->wiphy, "wrong echo %x != %x", v, echores);112		return -EINVAL;113	}114 115	return 0;116}117 118struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar,119	const enum carl9170_cmd_oids cmd, const unsigned int len)120{121	struct carl9170_cmd *tmp;122 123	tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);124	if (tmp) {125		tmp->hdr.cmd = cmd;126		tmp->hdr.len = len;127	}128 129	return tmp;130}131 132int carl9170_reboot(struct ar9170 *ar)133{134	struct carl9170_cmd *cmd;135	int err;136 137	cmd = carl9170_cmd_buf(ar, CARL9170_CMD_REBOOT_ASYNC, 0);138	if (!cmd)139		return -ENOMEM;140 141	err = __carl9170_exec_cmd(ar, cmd, true);142	return err;143}144 145int carl9170_mac_reset(struct ar9170 *ar)146{147	return carl9170_exec_cmd(ar, CARL9170_CMD_SWRST,148				 0, NULL, 0, NULL);149}150 151int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,152		       const u32 mode, const u32 addr, const u32 len)153{154	struct carl9170_cmd *cmd;155 156	cmd = carl9170_cmd_buf(ar, CARL9170_CMD_BCN_CTRL_ASYNC,157			       sizeof(struct carl9170_bcn_ctrl_cmd));158	if (!cmd)159		return -ENOMEM;160 161	cmd->bcn_ctrl.vif_id = cpu_to_le32(vif_id);162	cmd->bcn_ctrl.mode = cpu_to_le32(mode);163	cmd->bcn_ctrl.bcn_addr = cpu_to_le32(addr);164	cmd->bcn_ctrl.bcn_len = cpu_to_le32(len);165 166	return __carl9170_exec_cmd(ar, cmd, true);167}168 169int carl9170_collect_tally(struct ar9170 *ar)170{171	struct carl9170_tally_rsp tally;172	struct survey_info *info;173	unsigned int tick;174	int err;175 176	err = carl9170_exec_cmd(ar, CARL9170_CMD_TALLY, 0, NULL,177				sizeof(tally), (u8 *)&tally);178	if (err)179		return err;180 181	tick = le32_to_cpu(tally.tick);182	if (tick) {183		ar->tally.active += le32_to_cpu(tally.active) / tick;184		ar->tally.cca += le32_to_cpu(tally.cca) / tick;185		ar->tally.tx_time += le32_to_cpu(tally.tx_time) / tick;186		ar->tally.rx_total += le32_to_cpu(tally.rx_total);187		ar->tally.rx_overrun += le32_to_cpu(tally.rx_overrun);188 189		if (ar->channel) {190			info = &ar->survey[ar->channel->hw_value];191			info->time = ar->tally.active;192			info->time_busy = ar->tally.cca;193			info->time_tx = ar->tally.tx_time;194			do_div(info->time, 1000);195			do_div(info->time_busy, 1000);196			do_div(info->time_tx, 1000);197		}198	}199	return 0;200}201 202int carl9170_powersave(struct ar9170 *ar, const bool ps)203{204	struct carl9170_cmd *cmd;205	u32 state;206 207	cmd = carl9170_cmd_buf(ar, CARL9170_CMD_PSM_ASYNC,208			       sizeof(struct carl9170_psm));209	if (!cmd)210		return -ENOMEM;211 212	if (ps) {213		/* Sleep until next TBTT */214		state = CARL9170_PSM_SLEEP | 1;215	} else {216		/* wake up immediately */217		state = 1;218	}219 220	cmd->psm.state = cpu_to_le32(state);221	return __carl9170_exec_cmd(ar, cmd, true);222}223