My work on MemoryStick system
Subsystems (2)
Maxim Levitsky
maintainerPATCH 1/1 My work on MemoryStick system
Hi,
This patch series contains the work I did for memorystick subsystem.
I resend slightly cleaned up driver for my card reader in patch #2 patch #1 and #3 are new and add support for Legacy MemorySticks (<= 128MB)
Everything works and more or less tested.
Best regards,
Maxim Levitsky
Maxim Levitsky
maintainerPATCH 1/3 memstick: add few common helpers
I add here few helpers that should make memstick block driver a bit simplier.
Currently only my forthcoming ms_block.c will use them, but I plan to make mspro_blk use them too.
--- drivers/memstick/core/memstick.c | 109 ++++++++++++++++++++++++++++++++++++++ include/linux/memstick.h | 22 +++++++- 2 files changed, 130 insertions(+), 1 deletions(-)
drivers/memstick/core/memstick.c +109 -0
@@ -362,6 +362,13 @@ static int h_memstick_set_rw_addr(struct memstick_dev *card, } } + +static int h_mspro_block_default_bad (struct memstick_dev *card, +struct memstick_request **mrq) +{ +return -ENXIO ; +} +/** * memstick_set_rw_addr - issue SET_RW_REG_ADDR request and wait for it to * complete
@@ -377,6 +384,108 @@ int memstick_set_rw_addr(struct memstick_dev *card) }EXPORT_SYMBOL (memstick_set_rw_addr); + +/** +* memstick_fetch_request - initialize new request to use by request handler +* @card - card to use +* @mrq - request to initialize +*/ +void memstick_fetch_request (struct memstick_dev *card, +struct memstick_request **mrq) +{ +if (*mrq ==NULL ) { + *mrq = &card->current_mrq; + (*mrq)->error =0 ; + card->state =0 ; + } +} +EXPORT_SYMBOL (memstick_fetch_request); + +/** +* memstick_complete_req - signal that request is completed +* @card - card to use +* @mrq - request to use +* @error - result of the request +* +* Card drivers can use that function to signal end of request +*/ +int memstick_complete_request (struct memstick_dev *card, +struct memstick_request *req,int error) +{ +if (error) + req->error = error; + + card->state =-1 ; + card->next_request = h_mspro_block_default_bad; +complete (&card->mrq_complete); +return -EAGAIN ; +} +EXPORT_SYMBOL (memstick_complete_request); + +/** +* ms_send_int_request - optionaly init new MS_TPC_GET_INT. +* if last request already contains the int flags, reuse them +* returns 1 if new request was initialized +* Will artifictially return MEMSTICK_INT_CMDNAK if this function was +* called more that once in 300 msecs without memstick_finish_int_request +* in between +* @card - card to use +* @mrq - request to use +*/ + +int memstick_send_int_request (struct memstick_dev *card, +struct memstick_request *req) +{ +if (!card->int_polling) { + card->int_poll_start_time = jiffies; + card->int_polling = true; + }else if (time_after (jiffies, + card->int_poll_start_time +msecs_to_jiffies (300 ))) { + req->data[0 ] |=MEMSTICK_INT_CMDNAK ; +return 0 ; + } + +if ((card->caps &MEMSTICK_CAP_AUTO_GET_INT ) && req->need_card_int) { +BUG_ON (req->error); + req->data[0 ] = req->int_reg; + req->need_card_int =0 ; +return 0 ; + }else { +memstick_init_req (req,MS_TPC_GET_INT ,NULL ,1 ); +return 1 ; + } +} +EXPORT_SYMBOL (memstick_send_int_request); + +/** +* Signal success of int polling, and cancel timeout +* Use this if you use memstick_send_int_request +* @card - card to use +*/ +void memstick_finish_int_request (struct memstick_dev *card) +{ + card->int_polling = false; +} +EXPORT_SYMBOL (memstick_finish_int_request); + +/** +* memstick_do_request_handler - runs state machine untill it finishes +* helper to be used in card drivers +* @card - card to use +* next_request - the state machine +*/ +int memstick_do_request_handler (struct memstick_dev *card, +int (*next_request)(struct memstick_dev *card, +struct memstick_request **mrq)) +{ + card->next_request = next_request; +memstick_new_req (card->host); +wait_for_completion (&card->mrq_complete); +return card->current_mrq.error; +} +EXPORT_SYMBOL (memstick_do_request_handler); + +static struct memstick_dev *memstick_alloc_card (struct memstick_host *host) { struct memstick_dev *card = kzalloc(sizeof(struct memstick_dev),
include/linux/memstick.h +21 -1
@@ -247,7 +247,7 @@ struct memstick_request {struct scatterlist sg;struct {unsigned char data_len; -unsigned char data[15 ]; +unsigned char data[32 ]; }; }; };
@@ -270,6 +270,12 @@ struct memstick_dev {void (*start)(struct memstick_dev *card);struct device dev; + +/* Private area for request processing */ +bool int_polling; +unsigned long int_poll_start_time; +int state; +int caps; };struct memstick_host {
@@ -329,6 +335,20 @@ void memstick_new_req(struct memstick_host *host);int memstick_set_rw_addr (struct memstick_dev *card); +void memstick_fetch_request (struct memstick_dev *card, +struct memstick_request **mrq); +int memstick_complete_request (struct memstick_dev *card, +struct memstick_request *req,int error); + +int memstick_send_int_request (struct memstick_dev *card, +struct memstick_request *req); + +void memstick_finish_int_request (struct memstick_dev *card); + +int memstick_do_request_handler (struct memstick_dev *card, +int (*next_request)(struct memstick_dev *card, +struct memstick_request **mrq)); +static inline void *memstick_priv (struct memstick_host *host) {return (void *)host->private;
Signature · 1 line
1.7.0.4
Maxim Levitsky
maintainerPATCH 2/3 MEMSTICK: Add driver for Ricoh R5C592 Card reader.
In reply to Maxim Levitsky--- MAINTAINERS | 5 + drivers/memstick/host/Kconfig | 13 + drivers/memstick/host/Makefile | 1 + drivers/memstick/host/r592.c | 889 ++++++++++++++++++++++++++++++++++++++++ drivers/memstick/host/r592.h | 177 ++++++++ 5 files changed, 1085 insertions(+), 0 deletions(-) create mode 100644 drivers/memstick/host/r592.c create mode 100644 drivers/memstick/host/r592.h
MAINTAINERS +5 -0
@@ -4854,6 +4854,11 @@ S: Maintained F: drivers/mtd/nand/r852.c F: drivers/mtd/nand/r852.h +RICOH R5C592 MEMORYSTICK DRIVER +M: Maxim Levitsky <[email protected]> +S: Maintained +F: drivers/memstick/host/r592.* + RISCOM8 DRIVER S: Orphan F: Documentation/serial/riscom8.txt
drivers/memstick/host/Kconfig +13 -0
@@ -30,3 +30,16 @@ config MEMSTICK_JMICRON_38X To compile this driver as a module, choose M here: the module will be called jmb38x_ms. + +config MEMSTICK_R592 + tristate "Ricoh R5C592 MemoryStick interface support (EXPERIMENTAL)" + depends on EXPERIMENTAL && PCI + + help + Say Y here if you want to be able to access MemoryStick cards with + the Ricoh R5C592 MemoryStick card reader (which is part of 5 in one + multifunction reader) + + To compile this driver as a module, choose M here: the module will + be called r592. +
drivers/memstick/host/Makefile +1 -0
@@ -8,3 +8,4 @@ endif obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o +obj-$(CONFIG_MEMSTICK_R592) += r592.o
drivers/memstick/host/r592.c new file +889 -0
889 lines not on this page · raw message
drivers/memstick/host/r592.h new file +177 -0
178 lines not on this page · raw message
Signature · 1 line
1.7.0.4
Maxim Levitsky
maintainerPATCH 3/3 memstick: add support for Legacy memorysticks
In reply to Maxim LevitskyHuge thanks for Alex Dubov for code that this is based on and for lot, really lot of help he gave me in understanding MemorySticks and implementing this driver.
His help made this driver possible.
As any code that works with user data this driver isn't recommened to use with valuable data.
It tries its best though to avoid data corruption and possible damage to the card.
--- MAINTAINERS | 5 + drivers/memstick/core/Kconfig | 13 + drivers/memstick/core/Makefile | 2 +- drivers/memstick/core/ms_block.c | 2243 ++++++++++++++++++++++++++++++++++++++ drivers/memstick/core/ms_block.h | 236 ++++ drivers/memstick/host/r592.c | 2 +- 6 files changed, 2499 insertions(+), 2 deletions(-) create mode 100644 drivers/memstick/core/ms_block.c create mode 100644 drivers/memstick/core/ms_block.h
MAINTAINERS +5 -0
@@ -5375,6 +5375,11 @@ W: http://tifmxx.berlios.de/ S: Maintained F: drivers/memstick/host/tifm_ms.c +SONY MEMORYSTICK STANDARD SUPPORT +M: Maxim Levitsky <[email protected]> +S: Maintained +F: drivers/memstick/core/ms_block.* + SOUND M: Jaroslav Kysela <[email protected]> M: Takashi Iwai <[email protected]>
drivers/memstick/core/Kconfig +13 -0
@@ -24,3 +24,16 @@ config MSPRO_BLOCK support. This provides a block device driver, which you can use to mount the filesystem. Almost everyone wishing MemoryStick support should say Y or M here. + +config MS_BLOCK + tristate "MemoryStick Standard device driver" + depends on BLOCK && EXPERIMENTAL + help + Say Y here to enable the MemoryStick Standard device driver + support. This provides a block device driver, which you can use + to mount the filesystem. + This driver works with old (bulky) MemoryStick and MemoryStick Duo + but not PRO. Say Y if you have such card. + Driver is new and not yet well tested, thus it can damage your card + (even permanently) +
drivers/memstick/core/Makefile +1 -1
@@ -7,5 +7,5 @@ ifeq ($(CONFIG_MEMSTICK_DEBUG),y) endif obj-$(CONFIG_MEMSTICK) += memstick.o - +obj-$(CONFIG_MS_BLOCK) += ms_block.o obj-$(CONFIG_MSPRO_BLOCK) += mspro_block.o
drivers/memstick/core/ms_block.c new file +2243 -0
2,243 lines not on this page · raw message
drivers/memstick/core/ms_block.h new file +236 -0
236 lines not on this page · raw message
drivers/memstick/host/r592.c +1 -1
@@ -639,8 +639,8 @@ static irqreturn_t r592_irq(int irq, void *data)indicate that card was removed/inserted and/or present */ if (irq_status & (R592_REG_MSC_IRQ_INSERT |R592_REG_MSC_IRQ_REMOVE )) { - ret =IRQ_HANDLED ;bool card_was_added = irq_status &R592_REG_MSC_IRQ_INSERT ; + ret =IRQ_HANDLED ;message ("IRQ: card %s" , card_was_added ?"added" :"removed" );
Signature · 1 line
1.7.0.4
Maxim Levitsky
maintainerQuoted 4 lines · Maxim Levitsky
Hi,
This patch series contains the work I did for memorystick subsystem.
Quoted 9 lines
I resend slightly cleaned up driver for my card reader in patch #2 patch #1 and #3 are new and add support for Legacy MemorySticks (<= 128MB)
Everything works and more or less tested.
Best regards,
Maxim Levitsky
I just tested this series with Jmicron, and unfortunelly there are bugs.
* driver refuses to handle 26 byte TPC I use to read regs (sizeof(ms_registers). If I bump it to 32, it works.
* With this fix first few reads still fail.
That means that card isn't detected always because boot blocks might not be read.
Later card works fine.
* Also I found out that msproblk.c allocates memory for attributes IO using stock kmalloc, and hangs that to driver.
However if driver doesn't support such address, it will fail. I fixed that in my driver by properly calling dma_unmap_sg, and thus using SWIOTLB if necessary.
But Jmicron driver doesn't unmap its sg.
(Yet the system with Jmicron device has just one GB, so this isn't the problem I am seeing).
Best regards,
Maxim Levitsky
Alex Dubov
maintainerQuoted 6 lines
I just tested this series with Jmicron, and unfortunelly there are bugs.
* driver refuses to handle 26 byte TPC I use to read regs (
sizeof(ms_registers). If I bump it to 32, it works.
It will work with any multiply of 4 (24 and 28 work as well). It's a known "feature".
Quoted 7 lines
* With this fix first few reads still fail. That means that card isn't detected always because boot blocks might not
be read.
Later card works fine.
Quoted 5 lines
* Also I found out that
msproblk.callocates memory for attributes IO
using stock kmalloc, and hangs that to driver. However if driver doesn't support such address, it will fail.
Why would hardware do anything at all with attribute memory space?
Quoted 8 lines
I fixed that in my driver by properly calling
dma_unmap_sg, and thus
using SWIOTLB if necessary.
But Jmicron driver doesn't unmap its sg.
(Yet the system with Jmicron device has just one GB, so this isn't the
problem I am seeing).
Maxim Levitsky
maintainerQuoted 9 lines · Alex Dubov
Quoted 6 lines
I just tested this series with Jmicron, and unfortunelly there are bugs.
* driver refuses to handle 26 byte TPC I use to read regs (
sizeof(ms_registers). If I bump it to 32, it works.It will work with any multiply of 4 (24 and 28 work as well). It's a known "feature".
Then I bump the size of ms_registers to 32 and leave this as is. OK?
And I add a warning about this feature of some hardwares someplace.
But what about MS_TPC_GET_INT. This asks for single byte. Hardware has to support it.
Quoted 8 lines
Quoted 8 lines
* With this fix first few reads still fail. That means that card isn't detected always because boot blocks might not
be read.
Later card works fine.
Quoted 7 lines
Quoted 5 lines
* Also I found out that
msproblk.callocates memory for attributes IO
using stock kmalloc, and hangs that to driver. However if driver doesn't support such address, it will fail.Why would hardware do anything at all with attribute memory space?
Read it?
You allocate the memory with kmalloc, create a sg with sg_init_one and pass that to driver.
So therefore it can be from arbitrary address.
In fact swiotlb takes care of that, and I just forgot the dma_unmap_sg in my r592.c...
Quoted 5 lines
Quoted 5 lines
I fixed that in my driver by properly calling
dma_unmap_sg, and thus
using SWIOTLB if necessary.
But Jmicron driver doesn't unmap its sg.
It does btw, didn't notice....
Quoted 3 lines
Quoted 3 lines
(Yet the system with Jmicron device has just one GB, so this isn't the
problem I am seeing).
I found further problems in jmicron driver:
1. Serial mode doesn't work well.
I first read the boot block, and then enable parallel mode. I do so because boot block has a flag that tells if parallel mode is supported.
It turns out that sector reads often don't finish, especially first and often second one which contain boot blocks.
If I enable parallel mode right away problem goes away.
2. the MS_TPC_WRITE_LONG_DATA fail, therefore I can't write anything to the stick.
As soon as my driver starts to write a block, first MS_TPC_WRITE_LONG_DATA succeeds, but second one timeouts. (there is no MS_TPC_GET_INT in between, because of parallel mode).
Maybe I do something wrong in my ms_block.c, but I checked it many times, and it appears to be correct, and it works fine with r592.c
Best regards,
Maxim Levitsky
Alex Dubov
maintainerQuoted 8 lines
Quoted 2 lines
Quoted 2 lines
I just tested this series with Jmicron, and
unfortunelly
Quoted 3 lines
Quoted 3 lines
there are bugs.
* driver refuses to handle 26 byte TPC I use to
read regs
Quoted 1 line
Quoted 1 line
(
sizeof(ms_registers). If I bump it to 32, it
Quoted 8 lines
works.
Quoted 2 lines
It will work with any multiply of 4 (24 and 28 work as
well). It's a known
Quoted 1 line
"feature".
Then I bump the size of
ms_registersto 32 and leave this as is.
OK?
I'd rather minimize the transfer size, than increase it.
Quoted 6 lines
And I add a warning about this feature of some hardwares someplace.
But what about
MS_TPC_GET_INT. This asks for single byte. Hardware has to support it.
They've got a custom register for its value. GET_INT is implemented by different hardware than READ/WRITE_REG
Quoted 20 lines
Quoted 7 lines
Quoted 7 lines
* With this fix first few reads still fail.
That means that card isn't detected alwaysbecause boot
Quoted 5 lines
Quoted 5 lines
blocks might not
be read.
Later card works fine.* Also I found out that
msproblk.callocatesmemory for
Quoted 3 lines
Quoted 3 lines
attributes IO
using stock kmalloc, and hangs that to driver.
However if driver doesn't support such address,it will
Quoted 2 lines
Quoted 1 line
fail.
Quoted 8 lines
Quoted 1 line
Why would hardware do anything at all with attribute
memory space?
Read it?You allocate the memory with kmalloc, create a sg with
sg_init_oneand
pass that to driver.
So therefore it can be from arbitrary address.
Yes, indeed.
Quoted 4 lines
I found further problems in jmicron driver:
Quoted 10 lines
1. Serial mode doesn't work well.
I first read the boot block, and then enable parallel mode.
I do so because boot block has a flag that tells if parallel mode is
supported.
It turns out that sector reads often don't finish, especially first and
often second one which contain boot blocks.
If I enable parallel mode right away problem goes away.
They have really weird dependency between clock setup and operation mode. Try to use the clock setup values from the errata I've sent you. The order of register initialization and reset timing seems to affect the operation as well.
To summarize my opinion about it: if I had to design a card reader, I won't even look at anything, but TI chips. :-)
Quoted 23 lines
2. the
MS_TPC_WRITE_LONG_DATAfail, therefore I can't write anything to
the stick.As soon as my driver starts to write a block, first
MS_TPC_WRITE_LONG_DATAsucceeds, but second one timeouts. (there is noMS_TPC_GET_INTin between, because of parallel mode).Maybe I do something wrong in my
ms_block.c, but I checked it many
times, and it appears to be correct, and it works fine withr592.cBest regards,
Maxim Levitsky