diff options
author | Alex Dubov <oakad@yahoo.com> | 2008-03-19 20:01:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-03-19 21:53:37 -0400 |
commit | 962ee1b10bff5e99e9ecb2a5f4e6399a0214c9cf (patch) | |
tree | d04d3463c1f5d4a45faf151c4b7fd1735161edab /drivers/memstick/core | |
parent | ead70773608a5d97f81cb492f117d20b5e9f323e (diff) |
memstick: add support for 8-bit parallel mode
Newer MemoryStick (HG) cards and hosts support 8-bit parallel mode of
operation in addition to original 4-bit and 1-bit modes.
Signed-off-by: Alex Dubov <oakad@yahoo.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/memstick/core')
-rw-r--r-- | drivers/memstick/core/mspro_block.c | 81 |
1 files changed, 55 insertions, 26 deletions
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index e5356f97d076..557dbbba5cb2 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c | |||
@@ -816,12 +816,13 @@ static int mspro_block_wait_for_ced(struct memstick_dev *card) | |||
816 | return card->current_mrq.error; | 816 | return card->current_mrq.error; |
817 | } | 817 | } |
818 | 818 | ||
819 | static int mspro_block_switch_to_parallel(struct memstick_dev *card) | 819 | static int mspro_block_set_interface(struct memstick_dev *card, |
820 | unsigned char sys_reg) | ||
820 | { | 821 | { |
821 | struct memstick_host *host = card->host; | 822 | struct memstick_host *host = card->host; |
822 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 823 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
823 | struct mspro_param_register param = { | 824 | struct mspro_param_register param = { |
824 | .system = MEMSTICK_SYS_PAR4, | 825 | .system = sys_reg, |
825 | .data_count = 0, | 826 | .data_count = 0, |
826 | .data_address = 0, | 827 | .data_address = 0, |
827 | .tpc_param = 0 | 828 | .tpc_param = 0 |
@@ -833,41 +834,70 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card) | |||
833 | sizeof(param)); | 834 | sizeof(param)); |
834 | memstick_new_req(host); | 835 | memstick_new_req(host); |
835 | wait_for_completion(&card->mrq_complete); | 836 | wait_for_completion(&card->mrq_complete); |
836 | if (card->current_mrq.error) | 837 | return card->current_mrq.error; |
837 | return card->current_mrq.error; | 838 | } |
839 | |||
840 | static int mspro_block_switch_interface(struct memstick_dev *card) | ||
841 | { | ||
842 | struct memstick_host *host = card->host; | ||
843 | struct mspro_block_data *msb = memstick_get_drvdata(card); | ||
844 | int rc = 0; | ||
845 | |||
846 | if (msb->caps & MEMSTICK_CAP_PAR4) | ||
847 | rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR4); | ||
848 | else | ||
849 | return 0; | ||
850 | |||
851 | if (rc) { | ||
852 | printk(KERN_WARNING | ||
853 | "%s: could not switch to 4-bit mode, error %d\n", | ||
854 | card->dev.bus_id, rc); | ||
855 | return 0; | ||
856 | } | ||
838 | 857 | ||
839 | msb->system = MEMSTICK_SYS_PAR4; | 858 | msb->system = MEMSTICK_SYS_PAR4; |
840 | host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4); | 859 | host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4); |
860 | printk(KERN_INFO "%s: switching to 4-bit parallel mode\n", | ||
861 | card->dev.bus_id); | ||
862 | |||
863 | if (msb->caps & MEMSTICK_CAP_PAR8) { | ||
864 | rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR8); | ||
865 | |||
866 | if (!rc) { | ||
867 | msb->system = MEMSTICK_SYS_PAR8; | ||
868 | host->set_param(host, MEMSTICK_INTERFACE, | ||
869 | MEMSTICK_PAR8); | ||
870 | printk(KERN_INFO | ||
871 | "%s: switching to 8-bit parallel mode\n", | ||
872 | card->dev.bus_id); | ||
873 | } else | ||
874 | printk(KERN_WARNING | ||
875 | "%s: could not switch to 8-bit mode, error %d\n", | ||
876 | card->dev.bus_id, rc); | ||
877 | } | ||
841 | 878 | ||
842 | card->next_request = h_mspro_block_req_init; | 879 | card->next_request = h_mspro_block_req_init; |
843 | msb->mrq_handler = h_mspro_block_default; | 880 | msb->mrq_handler = h_mspro_block_default; |
844 | memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1); | 881 | memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1); |
845 | memstick_new_req(card->host); | 882 | memstick_new_req(card->host); |
846 | wait_for_completion(&card->mrq_complete); | 883 | wait_for_completion(&card->mrq_complete); |
884 | rc = card->current_mrq.error; | ||
847 | 885 | ||
848 | if (card->current_mrq.error) { | 886 | if (rc) { |
887 | printk(KERN_WARNING | ||
888 | "%s: interface error, trying to fall back to serial\n", | ||
889 | card->dev.bus_id); | ||
849 | msb->system = MEMSTICK_SYS_SERIAL; | 890 | msb->system = MEMSTICK_SYS_SERIAL; |
850 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); | 891 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); |
851 | msleep(1000); | 892 | msleep(10); |
852 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); | 893 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); |
853 | host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); | 894 | host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); |
854 | 895 | ||
855 | if (memstick_set_rw_addr(card)) | 896 | rc = memstick_set_rw_addr(card); |
856 | return card->current_mrq.error; | 897 | if (!rc) |
857 | 898 | rc = mspro_block_set_interface(card, msb->system); | |
858 | param.system = msb->system; | ||
859 | |||
860 | card->next_request = h_mspro_block_req_init; | ||
861 | msb->mrq_handler = h_mspro_block_default; | ||
862 | memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, ¶m, | ||
863 | sizeof(param)); | ||
864 | memstick_new_req(host); | ||
865 | wait_for_completion(&card->mrq_complete); | ||
866 | |||
867 | return -EFAULT; | ||
868 | } | 899 | } |
869 | 900 | return rc; | |
870 | return 0; | ||
871 | } | 901 | } |
872 | 902 | ||
873 | /* Memory allocated for attributes by this function should be freed by | 903 | /* Memory allocated for attributes by this function should be freed by |
@@ -1053,12 +1083,11 @@ static int mspro_block_init_card(struct memstick_dev *card) | |||
1053 | return -EIO; | 1083 | return -EIO; |
1054 | 1084 | ||
1055 | msb->caps = host->caps; | 1085 | msb->caps = host->caps; |
1056 | if (msb->caps & MEMSTICK_CAP_PAR4) { | 1086 | rc = mspro_block_switch_interface(card); |
1057 | if (mspro_block_switch_to_parallel(card)) | 1087 | if (rc) |
1058 | printk(KERN_WARNING "%s: could not switch to " | 1088 | return rc; |
1059 | "parallel interface\n", card->dev.bus_id); | ||
1060 | } | ||
1061 | 1089 | ||
1090 | msleep(200); | ||
1062 | rc = mspro_block_wait_for_ced(card); | 1091 | rc = mspro_block_wait_for_ced(card); |
1063 | if (rc) | 1092 | if (rc) |
1064 | return rc; | 1093 | return rc; |