18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Atheros CARL9170 driver 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Basic HW register/memory/command access functions 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> 78c2ecf20Sopenharmony_ci * Copyright 2010, Christian Lamparter <chunkeey@googlemail.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 108c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by 118c2ecf20Sopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 128c2ecf20Sopenharmony_ci * (at your option) any later version. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, 158c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 168c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 178c2ecf20Sopenharmony_ci * GNU General Public License for more details. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License 208c2ecf20Sopenharmony_ci * along with this program; see the file COPYING. If not, see 218c2ecf20Sopenharmony_ci * http://www.gnu.org/licenses/. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * This file incorporates work covered by the following copyright and 248c2ecf20Sopenharmony_ci * permission notice: 258c2ecf20Sopenharmony_ci * Copyright (c) 2007-2008 Atheros Communications, Inc. 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 288c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 298c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 328c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 338c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 348c2ecf20Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 358c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 368c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 378c2ecf20Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 388c2ecf20Sopenharmony_ci */ 398c2ecf20Sopenharmony_ci#ifndef __CMD_H 408c2ecf20Sopenharmony_ci#define __CMD_H 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#include "carl9170.h" 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* basic HW access */ 458c2ecf20Sopenharmony_ciint carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); 468c2ecf20Sopenharmony_ciint carl9170_read_reg(struct ar9170 *ar, const u32 reg, u32 *val); 478c2ecf20Sopenharmony_ciint carl9170_read_mreg(struct ar9170 *ar, const int nregs, 488c2ecf20Sopenharmony_ci const u32 *regs, u32 *out); 498c2ecf20Sopenharmony_ciint carl9170_echo_test(struct ar9170 *ar, u32 v); 508c2ecf20Sopenharmony_ciint carl9170_reboot(struct ar9170 *ar); 518c2ecf20Sopenharmony_ciint carl9170_mac_reset(struct ar9170 *ar); 528c2ecf20Sopenharmony_ciint carl9170_powersave(struct ar9170 *ar, const bool power_on); 538c2ecf20Sopenharmony_ciint carl9170_collect_tally(struct ar9170 *ar); 548c2ecf20Sopenharmony_ciint carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, 558c2ecf20Sopenharmony_ci const u32 mode, const u32 addr, const u32 len); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic inline int carl9170_flush_cab(struct ar9170 *ar, 588c2ecf20Sopenharmony_ci const unsigned int vif_id) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci return carl9170_bcn_ctrl(ar, vif_id, CARL9170_BCN_CTRL_DRAIN, 0, 0); 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic inline int carl9170_rx_filter(struct ar9170 *ar, 648c2ecf20Sopenharmony_ci const unsigned int _rx_filter) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci __le32 rx_filter = cpu_to_le32(_rx_filter); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci return carl9170_exec_cmd(ar, CARL9170_CMD_RX_FILTER, 698c2ecf20Sopenharmony_ci sizeof(rx_filter), (u8 *)&rx_filter, 708c2ecf20Sopenharmony_ci 0, NULL); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistruct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar, 748c2ecf20Sopenharmony_ci const enum carl9170_cmd_oids cmd, const unsigned int len); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* 778c2ecf20Sopenharmony_ci * Macros to facilitate writing multiple registers in a single 788c2ecf20Sopenharmony_ci * write-combining USB command. Note that when the first group 798c2ecf20Sopenharmony_ci * fails the whole thing will fail without any others attempted, 808c2ecf20Sopenharmony_ci * but you won't know which write in the group failed. 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci#define carl9170_regwrite_begin(ar) \ 838c2ecf20Sopenharmony_cido { \ 848c2ecf20Sopenharmony_ci int __nreg = 0, __err = 0; \ 858c2ecf20Sopenharmony_ci struct ar9170 *__ar = ar; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define carl9170_regwrite(r, v) do { \ 888c2ecf20Sopenharmony_ci __ar->cmd_buf[2 * __nreg + 1] = cpu_to_le32(r); \ 898c2ecf20Sopenharmony_ci __ar->cmd_buf[2 * __nreg + 2] = cpu_to_le32(v); \ 908c2ecf20Sopenharmony_ci __nreg++; \ 918c2ecf20Sopenharmony_ci if ((__nreg >= PAYLOAD_MAX / 2)) { \ 928c2ecf20Sopenharmony_ci if (IS_ACCEPTING_CMD(__ar)) \ 938c2ecf20Sopenharmony_ci __err = carl9170_exec_cmd(__ar, \ 948c2ecf20Sopenharmony_ci CARL9170_CMD_WREG, 8 * __nreg, \ 958c2ecf20Sopenharmony_ci (u8 *) &__ar->cmd_buf[1], 0, NULL); \ 968c2ecf20Sopenharmony_ci else \ 978c2ecf20Sopenharmony_ci goto __regwrite_out; \ 988c2ecf20Sopenharmony_ci \ 998c2ecf20Sopenharmony_ci __nreg = 0; \ 1008c2ecf20Sopenharmony_ci if (__err) \ 1018c2ecf20Sopenharmony_ci goto __regwrite_out; \ 1028c2ecf20Sopenharmony_ci } \ 1038c2ecf20Sopenharmony_ci} while (0) 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci#define carl9170_regwrite_finish() \ 1068c2ecf20Sopenharmony_ci__regwrite_out : \ 1078c2ecf20Sopenharmony_ci if (__err == 0 && __nreg) { \ 1088c2ecf20Sopenharmony_ci if (IS_ACCEPTING_CMD(__ar)) \ 1098c2ecf20Sopenharmony_ci __err = carl9170_exec_cmd(__ar, \ 1108c2ecf20Sopenharmony_ci CARL9170_CMD_WREG, 8 * __nreg, \ 1118c2ecf20Sopenharmony_ci (u8 *) &__ar->cmd_buf[1], 0, NULL); \ 1128c2ecf20Sopenharmony_ci __nreg = 0; \ 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci#define carl9170_regwrite_result() \ 1168c2ecf20Sopenharmony_ci __err; \ 1178c2ecf20Sopenharmony_ci} while (0) 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci#define carl9170_async_regwrite_get_buf() \ 1218c2ecf20Sopenharmony_cido { \ 1228c2ecf20Sopenharmony_ci __nreg = 0; \ 1238c2ecf20Sopenharmony_ci __cmd = carl9170_cmd_buf(__carl, CARL9170_CMD_WREG_ASYNC, \ 1248c2ecf20Sopenharmony_ci CARL9170_MAX_CMD_PAYLOAD_LEN); \ 1258c2ecf20Sopenharmony_ci if (__cmd == NULL) { \ 1268c2ecf20Sopenharmony_ci __err = -ENOMEM; \ 1278c2ecf20Sopenharmony_ci goto __async_regwrite_out; \ 1288c2ecf20Sopenharmony_ci } \ 1298c2ecf20Sopenharmony_ci} while (0) 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci#define carl9170_async_regwrite_begin(carl) \ 1328c2ecf20Sopenharmony_cido { \ 1338c2ecf20Sopenharmony_ci struct ar9170 *__carl = carl; \ 1348c2ecf20Sopenharmony_ci struct carl9170_cmd *__cmd; \ 1358c2ecf20Sopenharmony_ci unsigned int __nreg; \ 1368c2ecf20Sopenharmony_ci int __err = 0; \ 1378c2ecf20Sopenharmony_ci carl9170_async_regwrite_get_buf(); \ 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci#define carl9170_async_regwrite_flush() \ 1408c2ecf20Sopenharmony_cido { \ 1418c2ecf20Sopenharmony_ci if (__cmd == NULL || __nreg == 0) \ 1428c2ecf20Sopenharmony_ci break; \ 1438c2ecf20Sopenharmony_ci \ 1448c2ecf20Sopenharmony_ci if (IS_ACCEPTING_CMD(__carl) && __nreg) { \ 1458c2ecf20Sopenharmony_ci __cmd->hdr.len = 8 * __nreg; \ 1468c2ecf20Sopenharmony_ci __err = __carl9170_exec_cmd(__carl, __cmd, true); \ 1478c2ecf20Sopenharmony_ci __cmd = NULL; \ 1488c2ecf20Sopenharmony_ci break; \ 1498c2ecf20Sopenharmony_ci } \ 1508c2ecf20Sopenharmony_ci goto __async_regwrite_out; \ 1518c2ecf20Sopenharmony_ci} while (0) 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci#define carl9170_async_regwrite(r, v) do { \ 1548c2ecf20Sopenharmony_ci if (__cmd == NULL) \ 1558c2ecf20Sopenharmony_ci carl9170_async_regwrite_get_buf(); \ 1568c2ecf20Sopenharmony_ci __cmd->wreg.regs[__nreg].addr = cpu_to_le32(r); \ 1578c2ecf20Sopenharmony_ci __cmd->wreg.regs[__nreg].val = cpu_to_le32(v); \ 1588c2ecf20Sopenharmony_ci __nreg++; \ 1598c2ecf20Sopenharmony_ci if ((__nreg >= PAYLOAD_MAX / 2)) \ 1608c2ecf20Sopenharmony_ci carl9170_async_regwrite_flush(); \ 1618c2ecf20Sopenharmony_ci} while (0) 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci#define carl9170_async_regwrite_finish() do { \ 1648c2ecf20Sopenharmony_ci__async_regwrite_out: \ 1658c2ecf20Sopenharmony_ci if (__cmd != NULL && __err == 0) \ 1668c2ecf20Sopenharmony_ci carl9170_async_regwrite_flush(); \ 1678c2ecf20Sopenharmony_ci kfree(__cmd); \ 1688c2ecf20Sopenharmony_ci} while (0) \ 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci#define carl9170_async_regwrite_result() \ 1718c2ecf20Sopenharmony_ci __err; \ 1728c2ecf20Sopenharmony_ci} while (0) 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci#endif /* __CMD_H */ 175