Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
xcap
xcap-capability-linux
Commits
392e7419
Commit
392e7419
authored
Aug 09, 2011
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ath6kl-next' of master.kernel.org:/pub/scm/linux/kernel/git/kvalo/ath6kl
parents
53dd4b93
19703573
Changes
26
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
17957 additions
and
0 deletions
+17957
-0
drivers/net/wireless/ath/Kconfig
drivers/net/wireless/ath/Kconfig
+1
-0
drivers/net/wireless/ath/Makefile
drivers/net/wireless/ath/Makefile
+1
-0
drivers/net/wireless/ath/ath6kl/Kconfig
drivers/net/wireless/ath/ath6kl/Kconfig
+15
-0
drivers/net/wireless/ath/ath6kl/Makefile
drivers/net/wireless/ath/ath6kl/Makefile
+35
-0
drivers/net/wireless/ath/ath6kl/bmi.c
drivers/net/wireless/ath/ath6kl/bmi.c
+692
-0
drivers/net/wireless/ath/ath6kl/bmi.h
drivers/net/wireless/ath/ath6kl/bmi.h
+250
-0
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/cfg80211.c
+1538
-0
drivers/net/wireless/ath/ath6kl/cfg80211.h
drivers/net/wireless/ath/ath6kl/cfg80211.h
+39
-0
drivers/net/wireless/ath/ath6kl/common.h
drivers/net/wireless/ath/ath6kl/common.h
+180
-0
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/core.h
+544
-0
drivers/net/wireless/ath/ath6kl/debug.c
drivers/net/wireless/ath/ath6kl/debug.c
+150
-0
drivers/net/wireless/ath/ath6kl/debug.h
drivers/net/wireless/ath/ath6kl/debug.h
+105
-0
drivers/net/wireless/ath/ath6kl/hif-ops.h
drivers/net/wireless/ath/ath6kl/hif-ops.h
+72
-0
drivers/net/wireless/ath/ath6kl/hif.h
drivers/net/wireless/ath/ath6kl/hif.h
+207
-0
drivers/net/wireless/ath/ath6kl/htc.c
drivers/net/wireless/ath/ath6kl/htc.c
+2456
-0
drivers/net/wireless/ath/ath6kl/htc.h
drivers/net/wireless/ath/ath6kl/htc.h
+604
-0
drivers/net/wireless/ath/ath6kl/htc_hif.c
drivers/net/wireless/ath/ath6kl/htc_hif.c
+641
-0
drivers/net/wireless/ath/ath6kl/htc_hif.h
drivers/net/wireless/ath/ath6kl/htc_hif.h
+92
-0
drivers/net/wireless/ath/ath6kl/init.c
drivers/net/wireless/ath/ath6kl/init.c
+1303
-0
drivers/net/wireless/ath/ath6kl/main.c
drivers/net/wireless/ath/ath6kl/main.c
+1337
-0
drivers/net/wireless/ath/ath6kl/node.c
drivers/net/wireless/ath/ath6kl/node.c
+234
-0
drivers/net/wireless/ath/ath6kl/sdio.c
drivers/net/wireless/ath/ath6kl/sdio.c
+912
-0
drivers/net/wireless/ath/ath6kl/target.h
drivers/net/wireless/ath/ath6kl/target.h
+331
-0
drivers/net/wireless/ath/ath6kl/txrx.c
drivers/net/wireless/ath/ath6kl/txrx.c
+1457
-0
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.c
+2743
-0
drivers/net/wireless/ath/ath6kl/wmi.h
drivers/net/wireless/ath/ath6kl/wmi.h
+2018
-0
No files found.
drivers/net/wireless/ath/Kconfig
View file @
392e7419
...
...
@@ -25,5 +25,6 @@ config ATH_DEBUG
source "drivers/net/wireless/ath/ath5k/Kconfig"
source "drivers/net/wireless/ath/ath9k/Kconfig"
source "drivers/net/wireless/ath/carl9170/Kconfig"
source "drivers/net/wireless/ath/ath6kl/Kconfig"
endif
drivers/net/wireless/ath/Makefile
View file @
392e7419
obj-$(CONFIG_ATH5K)
+=
ath5k/
obj-$(CONFIG_ATH9K_HW)
+=
ath9k/
obj-$(CONFIG_CARL9170)
+=
carl9170/
obj-$(CONFIG_ATH6KL)
+=
ath6kl/
obj-$(CONFIG_ATH_COMMON)
+=
ath.o
...
...
drivers/net/wireless/ath/ath6kl/Kconfig
0 → 100644
View file @
392e7419
config ATH6KL
tristate "Atheros ath6kl support"
depends on MMC
depends on CFG80211
---help---
This module adds support for wireless adapters based on
Atheros AR6003 chipset running over SDIO. If you choose to
build it as a module, it will be called ath6kl. Pls note
that AR6002 and AR6001 are not supported by this driver.
config ATH6KL_DEBUG
bool "Atheros ath6kl debugging"
depends on ATH6KL
---help---
Enables debug support
drivers/net/wireless/ath/ath6kl/Makefile
0 → 100644
View file @
392e7419
#------------------------------------------------------------------------------
# Copyright (c) 2004-2010 Atheros Communications Inc.
# All rights reserved.
#
#
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
#
#
# Author(s): ="Atheros"
#------------------------------------------------------------------------------
obj-$(CONFIG_ATH6KL)
:=
ath6kl.o
ath6kl-y
+=
debug.o
ath6kl-y
+=
htc_hif.o
ath6kl-y
+=
htc.o
ath6kl-y
+=
bmi.o
ath6kl-y
+=
cfg80211.o
ath6kl-y
+=
init.o
ath6kl-y
+=
main.o
ath6kl-y
+=
txrx.o
ath6kl-y
+=
wmi.o
ath6kl-y
+=
node.o
ath6kl-y
+=
sdio.o
drivers/net/wireless/ath/ath6kl/bmi.c
0 → 100644
View file @
392e7419
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
#include "hif-ops.h"
#include "target.h"
#include "debug.h"
static
int
ath6kl_get_bmi_cmd_credits
(
struct
ath6kl
*
ar
)
{
u32
addr
;
unsigned
long
timeout
;
int
ret
;
ar
->
bmi
.
cmd_credits
=
0
;
/* Read the counter register to get the command credits */
addr
=
COUNT_DEC_ADDRESS
+
(
HTC_MAILBOX_NUM_MAX
+
ENDPOINT1
)
*
4
;
timeout
=
jiffies
+
msecs_to_jiffies
(
BMI_COMMUNICATION_TIMEOUT
);
while
(
time_before
(
jiffies
,
timeout
)
&&
!
ar
->
bmi
.
cmd_credits
)
{
/*
* Hit the credit counter with a 4-byte access, the first byte
* read will hit the counter and cause a decrement, while the
* remaining 3 bytes has no effect. The rationale behind this
* is to make all HIF accesses 4-byte aligned.
*/
ret
=
hif_read_write_sync
(
ar
,
addr
,
(
u8
*
)
&
ar
->
bmi
.
cmd_credits
,
4
,
HIF_RD_SYNC_BYTE_INC
);
if
(
ret
)
{
ath6kl_err
(
"Unable to decrement the command credit count register: %d
\n
"
,
ret
);
return
ret
;
}
/* The counter is only 8 bits.
* Ignore anything in the upper 3 bytes
*/
ar
->
bmi
.
cmd_credits
&=
0xFF
;
}
if
(
!
ar
->
bmi
.
cmd_credits
)
{
ath6kl_err
(
"bmi communication timeout
\n
"
);
return
-
ETIMEDOUT
;
}
return
0
;
}
static
int
ath6kl_bmi_get_rx_lkahd
(
struct
ath6kl
*
ar
,
bool
need_timeout
)
{
unsigned
long
timeout
;
u32
rx_word
=
0
;
int
ret
=
0
;
timeout
=
jiffies
+
msecs_to_jiffies
(
BMI_COMMUNICATION_TIMEOUT
);
while
((
!
need_timeout
||
time_before
(
jiffies
,
timeout
))
&&
!
rx_word
)
{
ret
=
hif_read_write_sync
(
ar
,
RX_LOOKAHEAD_VALID_ADDRESS
,
(
u8
*
)
&
rx_word
,
sizeof
(
rx_word
),
HIF_RD_SYNC_BYTE_INC
);
if
(
ret
)
{
ath6kl_err
(
"unable to read RX_LOOKAHEAD_VALID
\n
"
);
return
ret
;
}
/* all we really want is one bit */
rx_word
&=
(
1
<<
ENDPOINT1
);
}
if
(
!
rx_word
)
{
ath6kl_err
(
"bmi_recv_buf FIFO empty
\n
"
);
return
-
EINVAL
;
}
return
ret
;
}
static
int
ath6kl_bmi_send_buf
(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
)
{
int
ret
;
u32
addr
;
ret
=
ath6kl_get_bmi_cmd_credits
(
ar
);
if
(
ret
)
return
ret
;
addr
=
ar
->
mbox_info
.
htc_addr
;
ret
=
hif_read_write_sync
(
ar
,
addr
,
buf
,
len
,
HIF_WR_SYNC_BYTE_INC
);
if
(
ret
)
ath6kl_err
(
"unable to send the bmi data to the device
\n
"
);
return
ret
;
}
static
int
ath6kl_bmi_recv_buf
(
struct
ath6kl
*
ar
,
u8
*
buf
,
u32
len
,
bool
want_timeout
)
{
int
ret
;
u32
addr
;
/*
* During normal bootup, small reads may be required.
* Rather than issue an HIF Read and then wait as the Target
* adds successive bytes to the FIFO, we wait here until
* we know that response data is available.
*
* This allows us to cleanly timeout on an unexpected
* Target failure rather than risk problems at the HIF level.
* In particular, this avoids SDIO timeouts and possibly garbage
* data on some host controllers. And on an interconnect
* such as Compact Flash (as well as some SDIO masters) which
* does not provide any indication on data timeout, it avoids
* a potential hang or garbage response.
*
* Synchronization is more difficult for reads larger than the
* size of the MBOX FIFO (128B), because the Target is unable
* to push the 129th byte of data until AFTER the Host posts an
* HIF Read and removes some FIFO data. So for large reads the
* Host proceeds to post an HIF Read BEFORE all the data is
* actually available to read. Fortunately, large BMI reads do
* not occur in practice -- they're supported for debug/development.
*
* So Host/Target BMI synchronization is divided into these cases:
* CASE 1: length < 4
* Should not happen
*
* CASE 2: 4 <= length <= 128
* Wait for first 4 bytes to be in FIFO
* If CONSERVATIVE_BMI_READ is enabled, also wait for
* a BMI command credit, which indicates that the ENTIRE
* response is available in the the FIFO
*
* CASE 3: length > 128
* Wait for the first 4 bytes to be in FIFO
*
* For most uses, a small timeout should be sufficient and we will
* usually see a response quickly; but there may be some unusual
* (debug) cases of BMI_EXECUTE where we want an larger timeout.
* For now, we use an unbounded busy loop while waiting for
* BMI_EXECUTE.
*
* If BMI_EXECUTE ever needs to support longer-latency execution,
* especially in production, this code needs to be enhanced to sleep
* and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently
* a function of Host processor speed.
*/
if
(
len
>=
4
)
{
/* NB: Currently, always true */
ret
=
ath6kl_bmi_get_rx_lkahd
(
ar
,
want_timeout
);
if
(
ret
)
return
ret
;
}
addr
=
ar
->
mbox_info
.
htc_addr
;
ret
=
hif_read_write_sync
(
ar
,
addr
,
buf
,
len
,
HIF_RD_SYNC_BYTE_INC
);
if
(
ret
)
{
ath6kl_err
(
"Unable to read the bmi data from the device: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
int
ath6kl_bmi_done
(
struct
ath6kl
*
ar
)
{
int
ret
;
u32
cid
=
BMI_DONE
;
if
(
ar
->
bmi
.
done_sent
)
{
ath6kl_dbg
(
ATH6KL_DBG_BMI
,
"bmi done skipped
\n
"
);
return
0
;
}
ar
->
bmi
.
done_sent
=
true
;
ret
=
ath6kl_bmi_send_buf
(
ar
,
(
u8
*
)
&
cid
,
sizeof
(
cid
));
if
(
ret
)
{
ath6kl_err
(
"Unable to send bmi done: %d
\n
"
,
ret
);
return
ret
;
}
ath6kl_bmi_cleanup
(
ar
);
return
0
;
}
int
ath6kl_bmi_get_target_info
(
struct
ath6kl
*
ar
,
struct
ath6kl_bmi_target_info
*
targ_info
)
{
int
ret
;
u32
cid
=
BMI_GET_TARGET_INFO
;
if
(
ar
->
bmi
.
done_sent
)
{
ath6kl_err
(
"bmi done sent already, cmd %d disallowed
\n
"
,
cid
);
return
-
EACCES
;
}
ret
=
ath6kl_bmi_send_buf
(
ar
,
(
u8
*
)
&
cid
,
sizeof
(
cid
));
if
(
ret
)
{
ath6kl_err
(
"Unable to send get target info: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
ath6kl_bmi_recv_buf
(
ar
,
(
u8
*
)
&
targ_info
->
version
,
sizeof
(
targ_info
->
version
),
true
);
if
(
ret
)
{
ath6kl_err
(
"Unable to recv target info: %d
\n
"
,
ret
);
return
ret
;
}
if
(
le32_to_cpu
(
targ_info
->
version
)
==
TARGET_VERSION_SENTINAL
)
{
/* Determine how many bytes are in the Target's targ_info */
ret
=
ath6kl_bmi_recv_buf
(
ar
,
(
u8
*
)
&
targ_info
->
byte_count
,
sizeof
(
targ_info
->
byte_count
),
true
);
if
(
ret
)
{
ath6kl_err
(
"unable to read target info byte count: %d
\n
"
,
ret
);
return
ret
;
}
/*
* The target's targ_info doesn't match the host's targ_info.
* We need to do some backwards compatibility to make this work.
*/
if
(
le32_to_cpu
(
targ_info
->
byte_count
)
!=
sizeof
(
*
targ_info
))
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
/* Read the remainder of the targ_info */
ret
=
ath6kl_bmi_recv_buf
(
ar
,
((
u8
*
)
targ_info
)
+
sizeof
(
targ_info
->
byte_count
),
sizeof
(
*
targ_info
)
-
sizeof
(
targ_info
->
byte_count
),
true
);
if
(
ret
)
{
ath6kl_err
(
"Unable to read target info (%d bytes): %d
\n
"
,
targ_info
->
byte_count
,
ret
);
return
ret
;
}
}
ath6kl_dbg
(
ATH6KL_DBG_BMI
,
"target info (ver: 0x%x type: 0x%x)
\n
"
,
targ_info
->
version
,
targ_info
->
type
);
return
0
;
}
int
ath6kl_bmi_read
(
struct
ath6kl
*
ar
,
u32
addr
,
u8
*
buf
,
u32
len
)
{
u32
cid
=
BMI_READ_MEMORY
;
int
ret
;
u32
offset
;
u32
len_remain
,
rx_len
;
u16
size
;
if
(
ar
->
bmi
.
done_sent
)
{
ath6kl_err
(
"bmi done sent already, cmd %d disallowed
\n
"
,
cid
);
return
-
EACCES
;
}
size
=
BMI_DATASZ_MAX
+
sizeof
(
cid
)
+
sizeof
(
addr
)
+
sizeof
(
len
);
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
memset
(
ar
->
bmi
.
cmd_buf
,
0
,
size
);
ath6kl_dbg
(
ATH6KL_DBG_BMI
,
"bmi read memory: device: addr: 0x%x, len: %d
\n
"
,
addr
,
len
);
len_remain
=
len
;
while
(
len_remain
)
{
rx_len
=
(
len_remain
<
BMI_DATASZ_MAX
)
?
len_remain
:
BMI_DATASZ_MAX
;
offset
=
0
;
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
cid
,
sizeof
(
cid
));
offset
+=
sizeof
(
cid
);
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
addr
,
sizeof
(
addr
));
offset
+=
sizeof
(
addr
);
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
rx_len
,
sizeof
(
rx_len
));
offset
+=
sizeof
(
len
);
ret
=
ath6kl_bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
ath6kl_bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
rx_len
,
true
);
if
(
ret
)
{
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ret
);
return
ret
;
}
memcpy
(
&
buf
[
len
-
len_remain
],
ar
->
bmi
.
cmd_buf
,
rx_len
);
len_remain
-=
rx_len
;
addr
+=
rx_len
;
}
return
0
;
}
int
ath6kl_bmi_write
(
struct
ath6kl
*
ar
,
u32
addr
,
u8
*
buf
,
u32
len
)
{
u32
cid
=
BMI_WRITE_MEMORY
;
int
ret
;
u32
offset
;
u32
len_remain
,
tx_len
;
const
u32
header
=
sizeof
(
cid
)
+
sizeof
(
addr
)
+
sizeof
(
len
);
u8
aligned_buf
[
BMI_DATASZ_MAX
];
u8
*
src
;
if
(
ar
->
bmi
.
done_sent
)
{
ath6kl_err
(
"bmi done sent already, cmd %d disallowed
\n
"
,
cid
);
return
-
EACCES
;
}
if
((
BMI_DATASZ_MAX
+
header
)
>
MAX_BMI_CMDBUF_SZ
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
memset
(
ar
->
bmi
.
cmd_buf
,
0
,
BMI_DATASZ_MAX
+
header
);
ath6kl_dbg
(
ATH6KL_DBG_BMI
,
"bmi write memory: addr: 0x%x, len: %d
\n
"
,
addr
,
len
);
len_remain
=
len
;
while
(
len_remain
)
{
src
=
&
buf
[
len
-
len_remain
];
if
(
len_remain
<
(
BMI_DATASZ_MAX
-
header
))
{
if
(
len_remain
&
3
)
{
/* align it with 4 bytes */
len_remain
=
len_remain
+
(
4
-
(
len_remain
&
3
));
memcpy
(
aligned_buf
,
src
,
len_remain
);
src
=
aligned_buf
;
}
tx_len
=
len_remain
;
}
else
{
tx_len
=
(
BMI_DATASZ_MAX
-
header
);
}
offset
=
0
;
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
cid
,
sizeof
(
cid
));
offset
+=
sizeof
(
cid
);
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
addr
,
sizeof
(
addr
));
offset
+=
sizeof
(
addr
);
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
tx_len
,
sizeof
(
tx_len
));
offset
+=
sizeof
(
tx_len
);
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
src
,
tx_len
);
offset
+=
tx_len
;
ret
=
ath6kl_bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
return
ret
;
}
len_remain
-=
tx_len
;
addr
+=
tx_len
;
}
return
0
;
}
int
ath6kl_bmi_execute
(
struct
ath6kl
*
ar
,
u32
addr
,
u32
*
param
)
{
u32
cid
=
BMI_EXECUTE
;
int
ret
;
u32
offset
;
u16
size
;
if
(
ar
->
bmi
.
done_sent
)
{
ath6kl_err
(
"bmi done sent already, cmd %d disallowed
\n
"
,
cid
);
return
-
EACCES
;
}
size
=
sizeof
(
cid
)
+
sizeof
(
addr
)
+
sizeof
(
param
);
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
memset
(
ar
->
bmi
.
cmd_buf
,
0
,
size
);
ath6kl_dbg
(
ATH6KL_DBG_BMI
,
"bmi execute: addr: 0x%x, param: %d)
\n
"
,
addr
,
*
param
);
offset
=
0
;
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
cid
,
sizeof
(
cid
));
offset
+=
sizeof
(
cid
);
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
addr
,
sizeof
(
addr
));
offset
+=
sizeof
(
addr
);
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
param
,
sizeof
(
*
param
));
offset
+=
sizeof
(
*
param
);
ret
=
ath6kl_bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
ath6kl_bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
),
false
);
if
(
ret
)
{
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ret
);
return
ret
;
}
memcpy
(
param
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
));
return
0
;
}
int
ath6kl_bmi_set_app_start
(
struct
ath6kl
*
ar
,
u32
addr
)
{
u32
cid
=
BMI_SET_APP_START
;
int
ret
;
u32
offset
;
u16
size
;
if
(
ar
->
bmi
.
done_sent
)
{
ath6kl_err
(
"bmi done sent already, cmd %d disallowed
\n
"
,
cid
);
return
-
EACCES
;
}
size
=
sizeof
(
cid
)
+
sizeof
(
addr
);
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
memset
(
ar
->
bmi
.
cmd_buf
,
0
,
size
);
ath6kl_dbg
(
ATH6KL_DBG_BMI
,
"bmi set app start: addr: 0x%x
\n
"
,
addr
);
offset
=
0
;
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
cid
,
sizeof
(
cid
));
offset
+=
sizeof
(
cid
);
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
addr
,
sizeof
(
addr
));
offset
+=
sizeof
(
addr
);
ret
=
ath6kl_bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
int
ath6kl_bmi_reg_read
(
struct
ath6kl
*
ar
,
u32
addr
,
u32
*
param
)
{
u32
cid
=
BMI_READ_SOC_REGISTER
;
int
ret
;
u32
offset
;
u16
size
;
if
(
ar
->
bmi
.
done_sent
)
{
ath6kl_err
(
"bmi done sent already, cmd %d disallowed
\n
"
,
cid
);
return
-
EACCES
;
}
size
=
sizeof
(
cid
)
+
sizeof
(
addr
);
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
memset
(
ar
->
bmi
.
cmd_buf
,
0
,
size
);
ath6kl_dbg
(
ATH6KL_DBG_BMI
,
"bmi read SOC reg: addr: 0x%x
\n
"
,
addr
);
offset
=
0
;
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
cid
,
sizeof
(
cid
));
offset
+=
sizeof
(
cid
);
memcpy
(
&
(
ar
->
bmi
.
cmd_buf
[
offset
]),
&
addr
,
sizeof
(
addr
));
offset
+=
sizeof
(
addr
);
ret
=
ath6kl_bmi_send_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
offset
);
if
(
ret
)
{
ath6kl_err
(
"Unable to write to the device: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
ath6kl_bmi_recv_buf
(
ar
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
),
true
);
if
(
ret
)
{
ath6kl_err
(
"Unable to read from the device: %d
\n
"
,
ret
);
return
ret
;
}
memcpy
(
param
,
ar
->
bmi
.
cmd_buf
,
sizeof
(
*
param
));
return
0
;
}
int
ath6kl_bmi_reg_write
(
struct
ath6kl
*
ar
,
u32
addr
,
u32
param
)
{
u32
cid
=
BMI_WRITE_SOC_REGISTER
;
int
ret
;
u32
offset
;
u16
size
;
if
(
ar
->
bmi
.
done_sent
)
{
ath6kl_err
(
"bmi done sent already, cmd %d disallowed
\n
"
,
cid
);
return
-
EACCES
;
}
size
=
sizeof
(
cid
)
+
sizeof
(
addr
)
+
sizeof
(
param
);
if
(
size
>
MAX_BMI_CMDBUF_SZ
)
{
WARN_ON
(
1
);
return
-
EINVAL
;
}
memset
(
ar
->
bmi
.
cmd_buf
,
0
,
size
);
ath6kl_dbg
(
ATH6KL_DBG_BMI
,