diff options
author | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-11-11 05:17:33 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-11-13 05:34:29 -0500 |
commit | 66b693c3b84876d33afd35b9d717d8b9d07384c8 (patch) | |
tree | ef47e8bba54045d903dbe28d81eb30f78e127330 /drivers/net/wireless/ath/ath6kl/sdio.c | |
parent | bd24a50fe66ef1f64a84a3d02e0f464bb394bb9b (diff) |
ath6kl: move bmi calls to hif driver
In preparation for USB support which has it's own method for bmi.
Based on code by Kevin Fang.
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/sdio.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/sdio.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index beb5f9bf26af..080be036a27e 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -845,6 +845,166 @@ static int ath6kl_sdio_resume(struct ath6kl *ar) | |||
845 | return 0; | 845 | return 0; |
846 | } | 846 | } |
847 | 847 | ||
848 | static int ath6kl_sdio_bmi_credits(struct ath6kl *ar) | ||
849 | { | ||
850 | u32 addr; | ||
851 | unsigned long timeout; | ||
852 | int ret; | ||
853 | |||
854 | ar->bmi.cmd_credits = 0; | ||
855 | |||
856 | /* Read the counter register to get the command credits */ | ||
857 | addr = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4; | ||
858 | |||
859 | timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT); | ||
860 | while (time_before(jiffies, timeout) && !ar->bmi.cmd_credits) { | ||
861 | |||
862 | /* | ||
863 | * Hit the credit counter with a 4-byte access, the first byte | ||
864 | * read will hit the counter and cause a decrement, while the | ||
865 | * remaining 3 bytes has no effect. The rationale behind this | ||
866 | * is to make all HIF accesses 4-byte aligned. | ||
867 | */ | ||
868 | ret = ath6kl_sdio_read_write_sync(ar, addr, | ||
869 | (u8 *)&ar->bmi.cmd_credits, 4, | ||
870 | HIF_RD_SYNC_BYTE_INC); | ||
871 | if (ret) { | ||
872 | ath6kl_err("Unable to decrement the command credit " | ||
873 | "count register: %d\n", ret); | ||
874 | return ret; | ||
875 | } | ||
876 | |||
877 | /* The counter is only 8 bits. | ||
878 | * Ignore anything in the upper 3 bytes | ||
879 | */ | ||
880 | ar->bmi.cmd_credits &= 0xFF; | ||
881 | } | ||
882 | |||
883 | if (!ar->bmi.cmd_credits) { | ||
884 | ath6kl_err("bmi communication timeout\n"); | ||
885 | return -ETIMEDOUT; | ||
886 | } | ||
887 | |||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar) | ||
892 | { | ||
893 | unsigned long timeout; | ||
894 | u32 rx_word = 0; | ||
895 | int ret = 0; | ||
896 | |||
897 | timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT); | ||
898 | while ((time_before(jiffies, timeout)) && !rx_word) { | ||
899 | ret = ath6kl_sdio_read_write_sync(ar, | ||
900 | RX_LOOKAHEAD_VALID_ADDRESS, | ||
901 | (u8 *)&rx_word, sizeof(rx_word), | ||
902 | HIF_RD_SYNC_BYTE_INC); | ||
903 | if (ret) { | ||
904 | ath6kl_err("unable to read RX_LOOKAHEAD_VALID\n"); | ||
905 | return ret; | ||
906 | } | ||
907 | |||
908 | /* all we really want is one bit */ | ||
909 | rx_word &= (1 << ENDPOINT1); | ||
910 | } | ||
911 | |||
912 | if (!rx_word) { | ||
913 | ath6kl_err("bmi_recv_buf FIFO empty\n"); | ||
914 | return -EINVAL; | ||
915 | } | ||
916 | |||
917 | return ret; | ||
918 | } | ||
919 | |||
920 | static int ath6kl_sdio_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) | ||
921 | { | ||
922 | int ret; | ||
923 | u32 addr; | ||
924 | |||
925 | ret = ath6kl_sdio_bmi_credits(ar); | ||
926 | if (ret) | ||
927 | return ret; | ||
928 | |||
929 | addr = ar->mbox_info.htc_addr; | ||
930 | |||
931 | ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len, | ||
932 | HIF_WR_SYNC_BYTE_INC); | ||
933 | if (ret) | ||
934 | ath6kl_err("unable to send the bmi data to the device\n"); | ||
935 | |||
936 | return ret; | ||
937 | } | ||
938 | |||
939 | static int ath6kl_sdio_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | ||
940 | { | ||
941 | int ret; | ||
942 | u32 addr; | ||
943 | |||
944 | /* | ||
945 | * During normal bootup, small reads may be required. | ||
946 | * Rather than issue an HIF Read and then wait as the Target | ||
947 | * adds successive bytes to the FIFO, we wait here until | ||
948 | * we know that response data is available. | ||
949 | * | ||
950 | * This allows us to cleanly timeout on an unexpected | ||
951 | * Target failure rather than risk problems at the HIF level. | ||
952 | * In particular, this avoids SDIO timeouts and possibly garbage | ||
953 | * data on some host controllers. And on an interconnect | ||
954 | * such as Compact Flash (as well as some SDIO masters) which | ||
955 | * does not provide any indication on data timeout, it avoids | ||
956 | * a potential hang or garbage response. | ||
957 | * | ||
958 | * Synchronization is more difficult for reads larger than the | ||
959 | * size of the MBOX FIFO (128B), because the Target is unable | ||
960 | * to push the 129th byte of data until AFTER the Host posts an | ||
961 | * HIF Read and removes some FIFO data. So for large reads the | ||
962 | * Host proceeds to post an HIF Read BEFORE all the data is | ||
963 | * actually available to read. Fortunately, large BMI reads do | ||
964 | * not occur in practice -- they're supported for debug/development. | ||
965 | * | ||
966 | * So Host/Target BMI synchronization is divided into these cases: | ||
967 | * CASE 1: length < 4 | ||
968 | * Should not happen | ||
969 | * | ||
970 | * CASE 2: 4 <= length <= 128 | ||
971 | * Wait for first 4 bytes to be in FIFO | ||
972 | * If CONSERVATIVE_BMI_READ is enabled, also wait for | ||
973 | * a BMI command credit, which indicates that the ENTIRE | ||
974 | * response is available in the the FIFO | ||
975 | * | ||
976 | * CASE 3: length > 128 | ||
977 | * Wait for the first 4 bytes to be in FIFO | ||
978 | * | ||
979 | * For most uses, a small timeout should be sufficient and we will | ||
980 | * usually see a response quickly; but there may be some unusual | ||
981 | * (debug) cases of BMI_EXECUTE where we want an larger timeout. | ||
982 | * For now, we use an unbounded busy loop while waiting for | ||
983 | * BMI_EXECUTE. | ||
984 | * | ||
985 | * If BMI_EXECUTE ever needs to support longer-latency execution, | ||
986 | * especially in production, this code needs to be enhanced to sleep | ||
987 | * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently | ||
988 | * a function of Host processor speed. | ||
989 | */ | ||
990 | if (len >= 4) { /* NB: Currently, always true */ | ||
991 | ret = ath6kl_bmi_get_rx_lkahd(ar); | ||
992 | if (ret) | ||
993 | return ret; | ||
994 | } | ||
995 | |||
996 | addr = ar->mbox_info.htc_addr; | ||
997 | ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len, | ||
998 | HIF_RD_SYNC_BYTE_INC); | ||
999 | if (ret) { | ||
1000 | ath6kl_err("Unable to read the bmi data from the device: %d\n", | ||
1001 | ret); | ||
1002 | return ret; | ||
1003 | } | ||
1004 | |||
1005 | return 0; | ||
1006 | } | ||
1007 | |||
848 | static void ath6kl_sdio_stop(struct ath6kl *ar) | 1008 | static void ath6kl_sdio_stop(struct ath6kl *ar) |
849 | { | 1009 | { |
850 | struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); | 1010 | struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); |
@@ -889,6 +1049,8 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = { | |||
889 | .cleanup_scatter = ath6kl_sdio_cleanup_scatter, | 1049 | .cleanup_scatter = ath6kl_sdio_cleanup_scatter, |
890 | .suspend = ath6kl_sdio_suspend, | 1050 | .suspend = ath6kl_sdio_suspend, |
891 | .resume = ath6kl_sdio_resume, | 1051 | .resume = ath6kl_sdio_resume, |
1052 | .bmi_read = ath6kl_sdio_bmi_read, | ||
1053 | .bmi_write = ath6kl_sdio_bmi_write, | ||
892 | .power_on = ath6kl_sdio_power_on, | 1054 | .power_on = ath6kl_sdio_power_on, |
893 | .power_off = ath6kl_sdio_power_off, | 1055 | .power_off = ath6kl_sdio_power_off, |
894 | .stop = ath6kl_sdio_stop, | 1056 | .stop = ath6kl_sdio_stop, |