1 /* 2 * Atheros CARL9170 driver 3 * 4 * Basic HW register/memory/command access functions 5 * 6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (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 of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; see the file COPYING. If not, see 20 * http://www.gnu.org/licenses/. 21 * 22 * This file incorporates work covered by the following copyright and 23 * permission notice: 24 * Copyright (c) 2007-2008 Atheros Communications, Inc. 25 * 26 * Permission to use, copy, modify, and/or distribute this software for any 27 * purpose with or without fee is hereby granted, provided that the above 28 * copyright notice and this permission notice appear in all copies. 29 * 30 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 31 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 32 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 33 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 34 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 35 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 36 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 37 */ 38 39 #include "carl9170.h" 40 #include "cmd.h" 41 42 int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) 43 { 44 const __le32 buf[2] = { 45 cpu_to_le32(reg), 46 cpu_to_le32(val), 47 }; 48 int err; 49 50 err = carl9170_exec_cmd(ar, CARL9170_CMD_WREG, sizeof(buf), 51 (u8 *) buf, 0, NULL); 52 if (err) { 53 if (net_ratelimit()) { 54 wiphy_err(ar->hw->wiphy, "writing reg %#x " 55 "(val %#x) failed (%d)\n", reg, val, err); 56 } 57 } 58 return err; 59 } 60 61 int carl9170_read_mreg(struct ar9170 *ar, const int nregs, 62 const u32 *regs, u32 *out) 63 { 64 int i, err; 65 __le32 *offs, *res; 66 67 /* abuse "out" for the register offsets, must be same length */ 68 offs = (__le32 *)out; 69 for (i = 0; i < nregs; i++) 70 offs[i] = cpu_to_le32(regs[i]); 71 72 /* also use the same buffer for the input */ 73 res = (__le32 *)out; 74 75 err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG, 76 4 * nregs, (u8 *)offs, 77 4 * nregs, (u8 *)res); 78 if (err) { 79 if (net_ratelimit()) { 80 wiphy_err(ar->hw->wiphy, "reading regs failed (%d)\n", 81 err); 82 } 83 return err; 84 } 85 86 /* convert result to cpu endian */ 87 for (i = 0; i < nregs; i++) 88 out[i] = le32_to_cpu(res[i]); 89 90 return 0; 91 } 92 93 int carl9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val) 94 { 95 return carl9170_read_mreg(ar, 1, ®, val); 96 } 97 98 int carl9170_echo_test(struct ar9170 *ar, const u32 v) 99 { 100 u32 echores; 101 int err; 102 103 err = carl9170_exec_cmd(ar, CARL9170_CMD_ECHO, 104 4, (u8 *)&v, 105 4, (u8 *)&echores); 106 if (err) 107 return err; 108 109 if (v != echores) { 110 wiphy_info(ar->hw->wiphy, "wrong echo %x != %x", v, echores); 111 return -EINVAL; 112 } 113 114 return 0; 115 } 116 117 struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar, 118 const enum carl9170_cmd_oids cmd, const unsigned int len) 119 { 120 struct carl9170_cmd *tmp; 121 122 tmp = kzalloc(sizeof(struct carl9170_cmd_head) + len, GFP_ATOMIC); 123 if (tmp) { 124 tmp->hdr.cmd = cmd; 125 tmp->hdr.len = len; 126 } 127 128 return tmp; 129 } 130 131 int carl9170_reboot(struct ar9170 *ar) 132 { 133 struct carl9170_cmd *cmd; 134 int err; 135 136 cmd = carl9170_cmd_buf(ar, CARL9170_CMD_REBOOT_ASYNC, 0); 137 if (!cmd) 138 return -ENOMEM; 139 140 err = __carl9170_exec_cmd(ar, (struct carl9170_cmd *)cmd, true); 141 return err; 142 } 143 144 int carl9170_mac_reset(struct ar9170 *ar) 145 { 146 return carl9170_exec_cmd(ar, CARL9170_CMD_SWRST, 147 0, NULL, 0, NULL); 148 } 149 150 int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, 151 const u32 mode, const u32 addr, const u32 len) 152 { 153 struct carl9170_cmd *cmd; 154 155 cmd = carl9170_cmd_buf(ar, CARL9170_CMD_BCN_CTRL_ASYNC, 156 sizeof(struct carl9170_bcn_ctrl_cmd)); 157 if (!cmd) 158 return -ENOMEM; 159 160 cmd->bcn_ctrl.vif_id = cpu_to_le32(vif_id); 161 cmd->bcn_ctrl.mode = cpu_to_le32(mode); 162 cmd->bcn_ctrl.bcn_addr = cpu_to_le32(addr); 163 cmd->bcn_ctrl.bcn_len = cpu_to_le32(len); 164 165 return __carl9170_exec_cmd(ar, cmd, true); 166 } 167 168 int carl9170_powersave(struct ar9170 *ar, const bool ps) 169 { 170 struct carl9170_cmd *cmd; 171 u32 state; 172 173 cmd = carl9170_cmd_buf(ar, CARL9170_CMD_PSM_ASYNC, 174 sizeof(struct carl9170_psm)); 175 if (!cmd) 176 return -ENOMEM; 177 178 if (ps) { 179 /* Sleep until next TBTT */ 180 state = CARL9170_PSM_SLEEP | 1; 181 } else { 182 /* wake up immediately */ 183 state = 1; 184 } 185 186 cmd->psm.state = cpu_to_le32(state); 187 return __carl9170_exec_cmd(ar, cmd, true); 188 } 189