summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/mips/ingenic_x1000/msc-x1000.c43
-rw-r--r--firmware/target/mips/ingenic_x1000/msc-x1000.h3
2 files changed, 29 insertions, 17 deletions
diff --git a/firmware/target/mips/ingenic_x1000/msc-x1000.c b/firmware/target/mips/ingenic_x1000/msc-x1000.c
index 27929cced5..3b7df1dd01 100644
--- a/firmware/target/mips/ingenic_x1000/msc-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/msc-x1000.c
@@ -39,6 +39,8 @@
39 * ensure that removing the card always resets the driver to a sane state. 39 * ensure that removing the card always resets the driver to a sane state.
40 */ 40 */
41 41
42#define DEBOUNCE_TIME (HZ/10)
43
42static const msc_config msc_configs[] = { 44static const msc_config msc_configs[] = {
43#ifdef FIIO_M3K 45#ifdef FIIO_M3K
44#define MSC_CLOCK_SOURCE X1000_CLK_SCLK_A 46#define MSC_CLOCK_SOURCE X1000_CLK_SCLK_A
@@ -105,6 +107,7 @@ static void msc_init_one(msc_drv* d, int msc)
105 d->req = NULL; 107 d->req = NULL;
106 d->iflag_done = 0; 108 d->iflag_done = 0;
107 d->card_present = 1; 109 d->card_present = 1;
110 d->card_present_last = 1;
108 d->req_running = 0; 111 d->req_running = 0;
109 mutex_init(&d->lock); 112 mutex_init(&d->lock);
110 semaphore_init(&d->cmd_done, 1, 0); 113 semaphore_init(&d->cmd_done, 1, 0);
@@ -122,8 +125,10 @@ static void msc_init_one(msc_drv* d, int msc)
122 125
123 /* Setup the card detect IRQ */ 126 /* Setup the card detect IRQ */
124 if(d->config->cd_gpio != GPIO_NONE) { 127 if(d->config->cd_gpio != GPIO_NONE) {
125 if(gpio_get_level(d->config->cd_gpio) != d->config->cd_active_level) 128 if(gpio_get_level(d->config->cd_gpio) != d->config->cd_active_level) {
126 d->card_present = 0; 129 d->card_present = 0;
130 d->card_present_last = 0;
131 }
127 132
128 system_set_irq_handler(GPIO_TO_IRQ(d->config->cd_gpio), 133 system_set_irq_handler(GPIO_TO_IRQ(d->config->cd_gpio),
129 msc == 0 ? msc0_cd_interrupt : msc1_cd_interrupt); 134 msc == 0 ? msc0_cd_interrupt : msc1_cd_interrupt);
@@ -613,11 +618,25 @@ static void msc_interrupt(msc_drv* d)
613static int msc_cd_callback(struct timeout* tmo) 618static int msc_cd_callback(struct timeout* tmo)
614{ 619{
615 msc_drv* d = (msc_drv*)tmo->data; 620 msc_drv* d = (msc_drv*)tmo->data;
621 int now_present = msc_card_detect(d) ? 1 : 0;
622
623 /* If the CD pin level changed during the timeout interval, then the
624 * signal is not yet stable and we need to wait longer. */
625 if(now_present != d->card_present_last) {
626 d->card_present_last = now_present;
627 return DEBOUNCE_TIME;
628 }
616 629
617 /* If card is still present we assume the card is properly inserted */ 630 /* If there is a change, then broadcast the hotswap event */
618 if(msc_card_detect(d)) { 631 if(now_present != d->card_present) {
619 d->card_present = 1; 632 if(now_present) {
620 queue_broadcast(SYS_HOTSWAP_INSERTED, d->drive_nr); 633 d->card_present = 1;
634 queue_broadcast(SYS_HOTSWAP_INSERTED, d->drive_nr);
635 } else {
636 msc_async_abort(d, MSC_REQ_EXTRACTED);
637 d->card_present = 0;
638 queue_broadcast(SYS_HOTSWAP_EXTRACTED, d->drive_nr);
639 }
621 } 640 }
622 641
623 return 0; 642 return 0;
@@ -625,17 +644,9 @@ static int msc_cd_callback(struct timeout* tmo)
625 644
626static void msc_cd_interrupt(msc_drv* d) 645static void msc_cd_interrupt(msc_drv* d)
627{ 646{
628 if(!msc_card_detect(d)) { 647 /* Timer to debounce input */
629 /* Immediately abort and notify when removing a card */ 648 d->card_present_last = msc_card_detect(d) ? 1 : 0;
630 msc_async_abort(d, MSC_REQ_EXTRACTED); 649 timeout_register(&d->cd_tmo, msc_cd_callback, DEBOUNCE_TIME, (intptr_t)d);
631 if(d->card_present) {
632 d->card_present = 0;
633 queue_broadcast(SYS_HOTSWAP_EXTRACTED, d->drive_nr);
634 }
635 } else {
636 /* Timer to debounce input */
637 timeout_register(&d->cd_tmo, msc_cd_callback, HZ/4, (intptr_t)d);
638 }
639 650
640 /* Invert the IRQ */ 651 /* Invert the IRQ */
641 gpio_flip_edge_irq(d->config->cd_gpio); 652 gpio_flip_edge_irq(d->config->cd_gpio);
diff --git a/firmware/target/mips/ingenic_x1000/msc-x1000.h b/firmware/target/mips/ingenic_x1000/msc-x1000.h
index 70f67a70d6..b7b05b859d 100644
--- a/firmware/target/mips/ingenic_x1000/msc-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/msc-x1000.h
@@ -126,7 +126,8 @@ typedef struct msc_drv {
126 unsigned iflag_done; 126 unsigned iflag_done;
127 127
128 volatile int req_running; 128 volatile int req_running;
129 volatile int card_present; 129 volatile int card_present; /* Debounced status */
130 volatile int card_present_last; /* Status when we last polled it */
130 131
131 struct mutex lock; 132 struct mutex lock;
132 struct semaphore cmd_done; 133 struct semaphore cmd_done;