diff options
Diffstat (limited to 'firmware/target/mips')
-rw-r--r-- | firmware/target/mips/ingenic_x1000/msc-x1000.c | 43 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_x1000/msc-x1000.h | 3 |
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 | |||
42 | static const msc_config msc_configs[] = { | 44 | static 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) | |||
613 | static int msc_cd_callback(struct timeout* tmo) | 618 | static 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 | ||
626 | static void msc_cd_interrupt(msc_drv* d) | 645 | static 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; |