aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/omap.c152
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
98static int mmc_omap_enable_poll = 1;
99
100struct mmc_omap_host { 98struct 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
142static inline int
143mmc_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
150static ssize_t
151mmc_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
160static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
161
162static ssize_t
163mmc_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
169static ssize_t
170mmc_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
189static DEVICE_ATTR(enable_poll, 0664,
190 mmc_omap_show_enable_poll, mmc_omap_store_enable_poll);
191
192static void 139static void
193mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd) 140mmc_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
547static 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
556static 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
563static 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 */
596static void 494static void
597mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) 495mmc_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
1146no_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))