diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/omap.c | 152 |
1 files changed, 1 insertions, 151 deletions
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index adf679a157eb..7d17c899c394 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
@@ -95,8 +95,6 @@ | |||
95 | * when the cover switch is open */ | 95 | * when the cover switch is open */ |
96 | #define OMAP_MMC_SWITCH_POLL_DELAY 500 | 96 | #define OMAP_MMC_SWITCH_POLL_DELAY 500 |
97 | 97 | ||
98 | static int mmc_omap_enable_poll = 1; | ||
99 | |||
100 | struct mmc_omap_host { | 98 | struct mmc_omap_host { |
101 | int initialized; | 99 | int initialized; |
102 | int suspended; | 100 | int suspended; |
@@ -133,62 +131,11 @@ struct mmc_omap_host { | |||
133 | short power_pin; | 131 | short power_pin; |
134 | short wp_pin; | 132 | short wp_pin; |
135 | 133 | ||
136 | int switch_pin; | ||
137 | struct work_struct switch_work; | 134 | struct work_struct switch_work; |
138 | struct timer_list switch_timer; | 135 | struct timer_list switch_timer; |
139 | int switch_last_state; | 136 | int switch_last_state; |
140 | }; | 137 | }; |
141 | 138 | ||
142 | static inline int | ||
143 | mmc_omap_cover_is_open(struct mmc_omap_host *host) | ||
144 | { | ||
145 | if (host->switch_pin < 0) | ||
146 | return 0; | ||
147 | return omap_get_gpio_datain(host->switch_pin); | ||
148 | } | ||
149 | |||
150 | static ssize_t | ||
151 | mmc_omap_show_cover_switch(struct device *dev, | ||
152 | struct device_attribute *attr, char *buf) | ||
153 | { | ||
154 | struct mmc_omap_host *host = dev_get_drvdata(dev); | ||
155 | |||
156 | return sprintf(buf, "%s\n", mmc_omap_cover_is_open(host) ? "open" : | ||
157 | "closed"); | ||
158 | } | ||
159 | |||
160 | static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL); | ||
161 | |||
162 | static ssize_t | ||
163 | mmc_omap_show_enable_poll(struct device *dev, | ||
164 | struct device_attribute *attr, char *buf) | ||
165 | { | ||
166 | return snprintf(buf, PAGE_SIZE, "%d\n", mmc_omap_enable_poll); | ||
167 | } | ||
168 | |||
169 | static ssize_t | ||
170 | mmc_omap_store_enable_poll(struct device *dev, | ||
171 | struct device_attribute *attr, const char *buf, | ||
172 | size_t size) | ||
173 | { | ||
174 | int enable_poll; | ||
175 | |||
176 | if (sscanf(buf, "%10d", &enable_poll) != 1) | ||
177 | return -EINVAL; | ||
178 | |||
179 | if (enable_poll != mmc_omap_enable_poll) { | ||
180 | struct mmc_omap_host *host = dev_get_drvdata(dev); | ||
181 | |||
182 | mmc_omap_enable_poll = enable_poll; | ||
183 | if (enable_poll && host->switch_pin >= 0) | ||
184 | schedule_work(&host->switch_work); | ||
185 | } | ||
186 | return size; | ||
187 | } | ||
188 | |||
189 | static DEVICE_ATTR(enable_poll, 0664, | ||
190 | mmc_omap_show_enable_poll, mmc_omap_store_enable_poll); | ||
191 | |||
192 | static void | 139 | static void |
193 | mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd) | 140 | mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd) |
194 | { | 141 | { |
@@ -495,8 +442,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
495 | if (status & OMAP_MMC_STAT_CMD_TOUT) { | 442 | if (status & OMAP_MMC_STAT_CMD_TOUT) { |
496 | /* Timeouts are routine with some commands */ | 443 | /* Timeouts are routine with some commands */ |
497 | if (host->cmd) { | 444 | if (host->cmd) { |
498 | if (!mmc_omap_cover_is_open(host)) | 445 | dev_err(mmc_dev(host->mmc), |
499 | dev_err(mmc_dev(host->mmc), | ||
500 | "command timeout, CMD %d\n", | 446 | "command timeout, CMD %d\n", |
501 | host->cmd->opcode); | 447 | host->cmd->opcode); |
502 | host->cmd->error = -ETIMEDOUT; | 448 | host->cmd->error = -ETIMEDOUT; |
@@ -544,54 +490,6 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
544 | return IRQ_HANDLED; | 490 | return IRQ_HANDLED; |
545 | } | 491 | } |
546 | 492 | ||
547 | static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id) | ||
548 | { | ||
549 | struct mmc_omap_host *host = (struct mmc_omap_host *) dev_id; | ||
550 | |||
551 | schedule_work(&host->switch_work); | ||
552 | |||
553 | return IRQ_HANDLED; | ||
554 | } | ||
555 | |||
556 | static void mmc_omap_switch_timer(unsigned long arg) | ||
557 | { | ||
558 | struct mmc_omap_host *host = (struct mmc_omap_host *) arg; | ||
559 | |||
560 | schedule_work(&host->switch_work); | ||
561 | } | ||
562 | |||
563 | static void mmc_omap_switch_handler(struct work_struct *work) | ||
564 | { | ||
565 | struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, switch_work); | ||
566 | struct mmc_card *card; | ||
567 | static int complained = 0; | ||
568 | int cards = 0, cover_open; | ||
569 | |||
570 | if (host->switch_pin == -1) | ||
571 | return; | ||
572 | cover_open = mmc_omap_cover_is_open(host); | ||
573 | if (cover_open != host->switch_last_state) { | ||
574 | kobject_uevent(&host->dev->kobj, KOBJ_CHANGE); | ||
575 | host->switch_last_state = cover_open; | ||
576 | } | ||
577 | mmc_detect_change(host->mmc, 0); | ||
578 | list_for_each_entry(card, &host->mmc->cards, node) { | ||
579 | if (mmc_card_present(card)) | ||
580 | cards++; | ||
581 | } | ||
582 | if (mmc_omap_cover_is_open(host)) { | ||
583 | if (!complained) { | ||
584 | dev_info(mmc_dev(host->mmc), "cover is open\n"); | ||
585 | complained = 1; | ||
586 | } | ||
587 | if (mmc_omap_enable_poll) | ||
588 | mod_timer(&host->switch_timer, jiffies + | ||
589 | msecs_to_jiffies(OMAP_MMC_SWITCH_POLL_DELAY)); | ||
590 | } else { | ||
591 | complained = 0; | ||
592 | } | ||
593 | } | ||
594 | |||
595 | /* Prepare to transfer the next segment of a scatterlist */ | 493 | /* Prepare to transfer the next segment of a scatterlist */ |
596 | static void | 494 | static void |
597 | mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) | 495 | mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) |
@@ -1057,7 +955,6 @@ static int __init mmc_omap_probe(struct platform_device *pdev) | |||
1057 | * the card detect sensing. | 955 | * the card detect sensing. |
1058 | */ | 956 | */ |
1059 | host->power_pin = minfo->power_pin; | 957 | host->power_pin = minfo->power_pin; |
1060 | host->switch_pin = minfo->switch_pin; | ||
1061 | host->wp_pin = minfo->wp_pin; | 958 | host->wp_pin = minfo->wp_pin; |
1062 | host->use_dma = 1; | 959 | host->use_dma = 1; |
1063 | host->dma_ch = -1; | 960 | host->dma_ch = -1; |
@@ -1102,48 +999,10 @@ static int __init mmc_omap_probe(struct platform_device *pdev) | |||
1102 | host->dev = &pdev->dev; | 999 | host->dev = &pdev->dev; |
1103 | platform_set_drvdata(pdev, host); | 1000 | platform_set_drvdata(pdev, host); |
1104 | 1001 | ||
1105 | if (host->switch_pin >= 0) { | ||
1106 | INIT_WORK(&host->switch_work, mmc_omap_switch_handler); | ||
1107 | init_timer(&host->switch_timer); | ||
1108 | host->switch_timer.function = mmc_omap_switch_timer; | ||
1109 | host->switch_timer.data = (unsigned long) host; | ||
1110 | if (omap_request_gpio(host->switch_pin) != 0) { | ||
1111 | dev_warn(mmc_dev(host->mmc), "Unable to get GPIO pin for MMC cover switch\n"); | ||
1112 | host->switch_pin = -1; | ||
1113 | goto no_switch; | ||
1114 | } | ||
1115 | |||
1116 | omap_set_gpio_direction(host->switch_pin, 1); | ||
1117 | ret = request_irq(OMAP_GPIO_IRQ(host->switch_pin), | ||
1118 | mmc_omap_switch_irq, IRQF_TRIGGER_RISING, DRIVER_NAME, host); | ||
1119 | if (ret) { | ||
1120 | dev_warn(mmc_dev(host->mmc), "Unable to get IRQ for MMC cover switch\n"); | ||
1121 | omap_free_gpio(host->switch_pin); | ||
1122 | host->switch_pin = -1; | ||
1123 | goto no_switch; | ||
1124 | } | ||
1125 | ret = device_create_file(&pdev->dev, &dev_attr_cover_switch); | ||
1126 | if (ret == 0) { | ||
1127 | ret = device_create_file(&pdev->dev, &dev_attr_enable_poll); | ||
1128 | if (ret != 0) | ||
1129 | device_remove_file(&pdev->dev, &dev_attr_cover_switch); | ||
1130 | } | ||
1131 | if (ret) { | ||
1132 | dev_warn(mmc_dev(host->mmc), "Unable to create sysfs attributes\n"); | ||
1133 | free_irq(OMAP_GPIO_IRQ(host->switch_pin), host); | ||
1134 | omap_free_gpio(host->switch_pin); | ||
1135 | host->switch_pin = -1; | ||
1136 | goto no_switch; | ||
1137 | } | ||
1138 | if (mmc_omap_enable_poll && mmc_omap_cover_is_open(host)) | ||
1139 | schedule_work(&host->switch_work); | ||
1140 | } | ||
1141 | |||
1142 | mmc_add_host(mmc); | 1002 | mmc_add_host(mmc); |
1143 | 1003 | ||
1144 | return 0; | 1004 | return 0; |
1145 | 1005 | ||
1146 | no_switch: | ||
1147 | /* FIXME: Free other resources too. */ | 1006 | /* FIXME: Free other resources too. */ |
1148 | if (host) { | 1007 | if (host) { |
1149 | if (host->iclk && !IS_ERR(host->iclk)) | 1008 | if (host->iclk && !IS_ERR(host->iclk)) |
@@ -1182,15 +1041,6 @@ static int mmc_omap_remove(struct platform_device *pdev) | |||
1182 | 1041 | ||
1183 | if (host->power_pin >= 0) | 1042 | if (host->power_pin >= 0) |
1184 | omap_free_gpio(host->power_pin); | 1043 | omap_free_gpio(host->power_pin); |
1185 | if (host->switch_pin >= 0) { | ||
1186 | device_remove_file(&pdev->dev, &dev_attr_enable_poll); | ||
1187 | device_remove_file(&pdev->dev, &dev_attr_cover_switch); | ||
1188 | free_irq(OMAP_GPIO_IRQ(host->switch_pin), host); | ||
1189 | omap_free_gpio(host->switch_pin); | ||
1190 | host->switch_pin = -1; | ||
1191 | del_timer_sync(&host->switch_timer); | ||
1192 | flush_scheduled_work(); | ||
1193 | } | ||
1194 | if (host->iclk && !IS_ERR(host->iclk)) | 1044 | if (host->iclk && !IS_ERR(host->iclk)) |
1195 | clk_put(host->iclk); | 1045 | clk_put(host->iclk); |
1196 | if (host->fclk && !IS_ERR(host->fclk)) | 1046 | if (host->fclk && !IS_ERR(host->fclk)) |