~ubuntu-branches/ubuntu/trusty/linux-armadaxp/trusty

« back to all changes in this revision

Viewing changes to drivers/net/wireless/libertas/if_sdio.c

  • Committer: Package Import Robot
  • Author(s): Michael Casadevall, Bryan Wu, Dann Frazier, Michael Casadeall
  • Date: 2012-03-10 15:00:54 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120310150054-flugb39zon8vvgwe
Tags: 3.2.0-1600.1
[ Bryan Wu ]
* UBUNTU: import debian/debian.env and debian.armadaxp

[ Dann Frazier ]
* ARM: Armada XP: remove trailing '/' in dirnames in mvRules.mk

[ Michael Casadeall ]
* tools: add some tools for Marvell Armada XP processor
* kernel: timer tick hacking from Marvell
* kernel: Sheeva Errata: add delay on Sheeva when powering down
* net: add Marvell NFP netfilter
* net: socket and skb modifications made by Marvell
* miscdevice: add minor IDs for some Marvell Armada drivers
* fs: introduce memory pool for splice()
* video: EDID detection updates from Marvell Armada XP patchset
* video: backlight: add Marvell Dove LCD backlight driver
* video: display: add THS8200 display driver
* video: framebuffer: add Marvell Dove and Armada XP processor onchip LCD controller driver
* usbtest: add Interrupt transfer testing by Marvell Armada XP code
* usb: ehci: add support for Marvell EHCI controler
* tty/serial: 8250: add support for Marvell Armada XP processor and DeviceTree work
* rtc: add support for Marvell Armada XP onchip RTC controller
* net: pppoe: add Marvell ethernet NFP hook in PPPoE networking driver
* mtd: nand: add support for Marvell Armada XP Nand Flash Controller
* mtd: maps: add Marvell Armada XP specific map driver
* mmc: add support for Marvell Armada XP MMC/SD host controller
* i2c: add support for Marvell Armada XP onchip i2c bus controller
* hwmon: add Kconfig option for Armada XP onchip thermal sensor driver
* dmaengine: add Net DMA support for splice and update Marvell XOR DMA engine driver
* ata: add support for Marvell Armada XP SATA controller and update some quirks
* ARM: add Marvell Armada XP machine to mach-types
* ARM: oprofile: add support for Marvell PJ4B core
* ARM: mm: more ARMv6 switches for Marvell Armada XP
* ARM: remove static declaration to allow compilation
* ARM: alignment access fault trick
* ARM: mm: skip some fault fixing when run on NONE SMP ARMv6 mode during early abort event
* ARM: mm: add Marvell Sheeva CPU Architecture for PJ4B
* ARM: introduce optimized copy operation for Marvell Armada XP
* ARM: SAUCE: hardware breakpoint trick for Marvell Armada XP
* ARM: big endian and little endian tricks for Marvell Armada XP
* ARM: SAUCE: Add Marvell Armada XP build rules to arch/arm/kernel/Makefile
* ARM: vfp: add special handling for Marvell Armada XP
* ARM: add support for Marvell U-Boot
* ARM: add mv_controller_num for ARM PCI drivers
* ARM: add support for local PMUs, general SMP tweaks and cache flushing
* ARM: add Marvell device identifies in glue-proc.h
* ARM: add IPC driver support for Marvell platforms
* ARM: add DMA mapping for Marvell platforms
* ARM: add Sheeva errata and PJ4B code for booting
* ARM: update Kconfig and Makefile to include Marvell Armada XP platforms
* ARM: Armada XP: import LSP from Marvell for Armada XP 3.2 kernel enablement

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
30
 
31
31
#include <linux/kernel.h>
32
 
#include <linux/moduleparam.h>
 
32
#include <linux/module.h>
33
33
#include <linux/slab.h>
34
34
#include <linux/firmware.h>
35
35
#include <linux/netdevice.h>
39
39
#include <linux/mmc/sdio_ids.h>
40
40
#include <linux/mmc/sdio.h>
41
41
#include <linux/mmc/host.h>
 
42
#include <linux/pm_runtime.h>
42
43
 
43
44
#include "host.h"
44
45
#include "decl.h"
47
48
#include "cmd.h"
48
49
#include "if_sdio.h"
49
50
 
 
51
static void if_sdio_interrupt(struct sdio_func *func);
 
52
 
50
53
/* The if_sdio_remove() callback function is called when
51
54
 * user removes this module from kernel space or ejects
52
55
 * the card from the slot. The driver handles these 2 cases
757
760
        return ret;
758
761
}
759
762
 
 
763
/********************************************************************/
 
764
/* Power management                                                 */
 
765
/********************************************************************/
 
766
 
 
767
static int if_sdio_power_on(struct if_sdio_card *card)
 
768
{
 
769
        struct sdio_func *func = card->func;
 
770
        struct lbs_private *priv = card->priv;
 
771
        struct mmc_host *host = func->card->host;
 
772
        int ret;
 
773
 
 
774
        sdio_claim_host(func);
 
775
 
 
776
        ret = sdio_enable_func(func);
 
777
        if (ret)
 
778
                goto release;
 
779
 
 
780
        /* For 1-bit transfers to the 8686 model, we need to enable the
 
781
         * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
 
782
         * bit to allow access to non-vendor registers. */
 
783
        if ((card->model == MODEL_8686) &&
 
784
            (host->caps & MMC_CAP_SDIO_IRQ) &&
 
785
            (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
 
786
                u8 reg;
 
787
 
 
788
                func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
 
789
                reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
 
790
                if (ret)
 
791
                        goto disable;
 
792
 
 
793
                reg |= SDIO_BUS_ECSI;
 
794
                sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
 
795
                if (ret)
 
796
                        goto disable;
 
797
        }
 
798
 
 
799
        card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
 
800
        if (ret)
 
801
                goto disable;
 
802
 
 
803
        card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
 
804
        if (ret)
 
805
                goto disable;
 
806
 
 
807
        card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
 
808
        if (ret)
 
809
                goto disable;
 
810
 
 
811
        sdio_release_host(func);
 
812
        ret = if_sdio_prog_firmware(card);
 
813
        sdio_claim_host(func);
 
814
        if (ret)
 
815
                goto disable;
 
816
 
 
817
        /*
 
818
         * Get rx_unit if the chip is SD8688 or newer.
 
819
         * SD8385 & SD8686 do not have rx_unit.
 
820
         */
 
821
        if ((card->model != MODEL_8385)
 
822
                        && (card->model != MODEL_8686))
 
823
                card->rx_unit = if_sdio_read_rx_unit(card);
 
824
        else
 
825
                card->rx_unit = 0;
 
826
 
 
827
        /*
 
828
         * Set up the interrupt handler late.
 
829
         *
 
830
         * If we set it up earlier, the (buggy) hardware generates a spurious
 
831
         * interrupt, even before the interrupt has been enabled, with
 
832
         * CCCR_INTx = 0.
 
833
         *
 
834
         * We register the interrupt handler late so that we can handle any
 
835
         * spurious interrupts, and also to avoid generation of that known
 
836
         * spurious interrupt in the first place.
 
837
         */
 
838
        ret = sdio_claim_irq(func, if_sdio_interrupt);
 
839
        if (ret)
 
840
                goto disable;
 
841
 
 
842
        /*
 
843
         * Enable interrupts now that everything is set up
 
844
         */
 
845
        sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
 
846
        if (ret)
 
847
                goto release_irq;
 
848
 
 
849
        sdio_release_host(func);
 
850
 
 
851
        /*
 
852
         * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
 
853
         */
 
854
        if (card->model == MODEL_8688) {
 
855
                struct cmd_header cmd;
 
856
 
 
857
                memset(&cmd, 0, sizeof(cmd));
 
858
 
 
859
                lbs_deb_sdio("send function INIT command\n");
 
860
                if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
 
861
                                lbs_cmd_copyback, (unsigned long) &cmd))
 
862
                        netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
 
863
        }
 
864
 
 
865
        priv->fw_ready = 1;
 
866
 
 
867
        return 0;
 
868
 
 
869
release_irq:
 
870
        sdio_release_irq(func);
 
871
disable:
 
872
        sdio_disable_func(func);
 
873
release:
 
874
        sdio_release_host(func);
 
875
        return ret;
 
876
}
 
877
 
 
878
static int if_sdio_power_off(struct if_sdio_card *card)
 
879
{
 
880
        struct sdio_func *func = card->func;
 
881
        struct lbs_private *priv = card->priv;
 
882
 
 
883
        priv->fw_ready = 0;
 
884
 
 
885
        sdio_claim_host(func);
 
886
        sdio_release_irq(func);
 
887
        sdio_disable_func(func);
 
888
        sdio_release_host(func);
 
889
        return 0;
 
890
}
 
891
 
 
892
 
760
893
/*******************************************************************/
761
894
/* Libertas callbacks                                              */
762
895
/*******************************************************************/
892
1025
 
893
1026
}
894
1027
 
 
1028
static struct mmc_host *reset_host;
 
1029
 
 
1030
static void if_sdio_reset_card_worker(struct work_struct *work)
 
1031
{
 
1032
        /*
 
1033
         * The actual reset operation must be run outside of lbs_thread. This
 
1034
         * is because mmc_remove_host() will cause the device to be instantly
 
1035
         * destroyed, and the libertas driver then needs to end lbs_thread,
 
1036
         * leading to a deadlock.
 
1037
         *
 
1038
         * We run it in a workqueue totally independent from the if_sdio_card
 
1039
         * instance for that reason.
 
1040
         */
 
1041
 
 
1042
        pr_info("Resetting card...");
 
1043
        mmc_remove_host(reset_host);
 
1044
        mmc_add_host(reset_host);
 
1045
}
 
1046
static DECLARE_WORK(card_reset_work, if_sdio_reset_card_worker);
 
1047
 
 
1048
static void if_sdio_reset_card(struct lbs_private *priv)
 
1049
{
 
1050
        struct if_sdio_card *card = priv->card;
 
1051
 
 
1052
        if (work_pending(&card_reset_work))
 
1053
                return;
 
1054
 
 
1055
        reset_host = card->func->card->host;
 
1056
        schedule_work(&card_reset_work);
 
1057
}
 
1058
 
 
1059
static int if_sdio_power_save(struct lbs_private *priv)
 
1060
{
 
1061
        struct if_sdio_card *card = priv->card;
 
1062
        int ret;
 
1063
 
 
1064
        flush_workqueue(card->workqueue);
 
1065
 
 
1066
        ret = if_sdio_power_off(card);
 
1067
 
 
1068
        /* Let runtime PM know the card is powered off */
 
1069
        pm_runtime_put_sync(&card->func->dev);
 
1070
 
 
1071
        return ret;
 
1072
}
 
1073
 
 
1074
static int if_sdio_power_restore(struct lbs_private *priv)
 
1075
{
 
1076
        struct if_sdio_card *card = priv->card;
 
1077
 
 
1078
        /* Make sure the card will not be powered off by runtime PM */
 
1079
        pm_runtime_get_sync(&card->func->dev);
 
1080
 
 
1081
        return if_sdio_power_on(card);
 
1082
}
 
1083
 
 
1084
 
895
1085
/*******************************************************************/
896
1086
/* SDIO callbacks                                                  */
897
1087
/*******************************************************************/
945
1135
        int ret, i;
946
1136
        unsigned int model;
947
1137
        struct if_sdio_packet *packet;
948
 
        struct mmc_host *host = func->card->host;
949
1138
 
950
1139
        lbs_deb_enter(LBS_DEB_SDIO);
951
1140
 
1002
1191
                goto free;
1003
1192
        }
1004
1193
 
1005
 
        sdio_claim_host(func);
1006
 
 
1007
 
        ret = sdio_enable_func(func);
1008
 
        if (ret)
1009
 
                goto release;
1010
 
 
1011
 
        /* For 1-bit transfers to the 8686 model, we need to enable the
1012
 
         * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
1013
 
         * bit to allow access to non-vendor registers. */
1014
 
        if ((card->model == MODEL_8686) &&
1015
 
            (host->caps & MMC_CAP_SDIO_IRQ) &&
1016
 
            (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
1017
 
                u8 reg;
1018
 
 
1019
 
                func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
1020
 
                reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
1021
 
                if (ret)
1022
 
                        goto release_int;
1023
 
 
1024
 
                reg |= SDIO_BUS_ECSI;
1025
 
                sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
1026
 
                if (ret)
1027
 
                        goto release_int;
1028
 
        }
1029
 
 
1030
 
        card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
1031
 
        if (ret)
1032
 
                goto release_int;
1033
 
 
1034
 
        card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
1035
 
        if (ret)
1036
 
                goto release_int;
1037
 
 
1038
 
        card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
1039
 
        if (ret)
1040
 
                goto release_int;
1041
 
 
1042
 
        sdio_release_host(func);
1043
 
 
1044
1194
        sdio_set_drvdata(func, card);
1045
1195
 
1046
1196
        lbs_deb_sdio("class = 0x%X, vendor = 0x%X, "
1048
1198
                        func->class, func->vendor, func->device,
1049
1199
                        model, (unsigned)card->ioport);
1050
1200
 
1051
 
        ret = if_sdio_prog_firmware(card);
1052
 
        if (ret)
1053
 
                goto reclaim;
1054
1201
 
1055
1202
        priv = lbs_add_card(card, &func->dev);
1056
1203
        if (!priv) {
1057
1204
                ret = -ENOMEM;
1058
 
                goto reclaim;
 
1205
                goto free;
1059
1206
        }
1060
1207
 
1061
1208
        card->priv = priv;
1065
1212
        priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
1066
1213
        priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
1067
1214
        priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
1068
 
 
1069
 
        sdio_claim_host(func);
1070
 
 
1071
 
        /*
1072
 
         * Get rx_unit if the chip is SD8688 or newer.
1073
 
         * SD8385 & SD8686 do not have rx_unit.
1074
 
         */
1075
 
        if ((card->model != MODEL_8385)
1076
 
                        && (card->model != MODEL_8686))
1077
 
                card->rx_unit = if_sdio_read_rx_unit(card);
1078
 
        else
1079
 
                card->rx_unit = 0;
1080
 
 
1081
 
        /*
1082
 
         * Set up the interrupt handler late.
1083
 
         *
1084
 
         * If we set it up earlier, the (buggy) hardware generates a spurious
1085
 
         * interrupt, even before the interrupt has been enabled, with
1086
 
         * CCCR_INTx = 0.
1087
 
         *
1088
 
         * We register the interrupt handler late so that we can handle any
1089
 
         * spurious interrupts, and also to avoid generation of that known
1090
 
         * spurious interrupt in the first place.
1091
 
         */
1092
 
        ret = sdio_claim_irq(func, if_sdio_interrupt);
1093
 
        if (ret)
1094
 
                goto disable;
1095
 
 
1096
 
        /*
1097
 
         * Enable interrupts now that everything is set up
1098
 
         */
1099
 
        sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
1100
 
        sdio_release_host(func);
1101
 
        if (ret)
1102
 
                goto reclaim;
1103
 
 
1104
 
        priv->fw_ready = 1;
1105
 
 
1106
 
        /*
1107
 
         * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
1108
 
         */
1109
 
        if (card->model == MODEL_8688) {
1110
 
                struct cmd_header cmd;
1111
 
 
1112
 
                memset(&cmd, 0, sizeof(cmd));
1113
 
 
1114
 
                lbs_deb_sdio("send function INIT command\n");
1115
 
                if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
1116
 
                                lbs_cmd_copyback, (unsigned long) &cmd))
1117
 
                        netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
1118
 
        }
 
1215
        priv->reset_card = if_sdio_reset_card;
 
1216
        priv->power_save = if_sdio_power_save;
 
1217
        priv->power_restore = if_sdio_power_restore;
 
1218
 
 
1219
        ret = if_sdio_power_on(card);
 
1220
        if (ret)
 
1221
                goto err_activate_card;
1119
1222
 
1120
1223
        ret = lbs_start_card(priv);
 
1224
        if_sdio_power_off(card);
1121
1225
        if (ret)
1122
1226
                goto err_activate_card;
1123
1227
 
 
1228
        /* Tell PM core that we don't need the card to be powered now */
 
1229
        pm_runtime_put_noidle(&func->dev);
 
1230
 
1124
1231
out:
1125
1232
        lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
1126
1233
 
1129
1236
err_activate_card:
1130
1237
        flush_workqueue(card->workqueue);
1131
1238
        lbs_remove_card(priv);
1132
 
reclaim:
1133
 
        sdio_claim_host(func);
1134
 
release_int:
1135
 
        sdio_release_irq(func);
1136
 
disable:
1137
 
        sdio_disable_func(func);
1138
 
release:
1139
 
        sdio_release_host(func);
1140
1239
free:
1141
1240
        destroy_workqueue(card->workqueue);
1142
1241
        while (card->packets) {
1163
1262
 
1164
1263
        card = sdio_get_drvdata(func);
1165
1264
 
 
1265
        /* Undo decrement done above in if_sdio_probe */
 
1266
        pm_runtime_get_noresume(&func->dev);
 
1267
 
1166
1268
        if (user_rmmod && (card->model == MODEL_8688)) {
1167
1269
                /*
1168
1270
                 * FUNC_SHUTDOWN is required for SD8688 WLAN/BT
1187
1289
        flush_workqueue(card->workqueue);
1188
1290
        destroy_workqueue(card->workqueue);
1189
1291
 
1190
 
        sdio_claim_host(func);
1191
 
        sdio_release_irq(func);
1192
 
        sdio_disable_func(func);
1193
 
        sdio_release_host(func);
1194
 
 
1195
1292
        while (card->packets) {
1196
1293
                packet = card->packets;
1197
1294
                card->packets = card->packets->next;
1301
1398
        /* Set the flag as user is removing this module. */
1302
1399
        user_rmmod = 1;
1303
1400
 
 
1401
        cancel_work_sync(&card_reset_work);
 
1402
 
1304
1403
        sdio_unregister_driver(&if_sdio_driver);
1305
1404
 
1306
1405
        lbs_deb_leave(LBS_DEB_SDIO);