* [PATCH 06/18] MMC: OMAP: Add back cover switch support
@ 2008-03-14 19:36 Carlos Aguiar
0 siblings, 0 replies; 3+ messages in thread
From: Carlos Aguiar @ 2008-03-14 19:36 UTC (permalink / raw)
To: Pierre Ossman; +Cc: Tony Lindgren, linux-kernel
From: Juha Yrjola <juha.yrjola@solidboot.com>
This patch adds back MMC cover switch support in a way that
supports multiple slots.
Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Signed-off-by: Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/mmc/host/omap.c | 92 ++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 89 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 05e7650..5175c18 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -106,6 +106,10 @@ struct mmc_omap_slot {
unsigned int fclk_freq;
unsigned powered:1;
+ struct work_struct switch_work;
+ struct timer_list switch_timer;
+ unsigned cover_open;
+
struct mmc_request *mrq;
struct mmc_omap_host *host;
struct mmc_host *mmc;
@@ -226,6 +230,25 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot)
spin_unlock_irqrestore(&host->slot_lock, flags);
}
+static inline
+int mmc_omap_cover_is_open(struct mmc_omap_slot *slot)
+{
+ return slot->pdata->get_cover_state(mmc_dev(slot->mmc), slot->id);
+}
+
+static ssize_t
+mmc_omap_show_cover_switch(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
+ struct mmc_omap_slot *slot = mmc_priv(mmc);
+
+ return sprintf(buf, "%s\n", mmc_omap_cover_is_open(slot) ? "open" :
+ "closed");
+}
+
+static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
+
static ssize_t
mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -544,9 +567,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
if (host->cmd) {
struct mmc_omap_slot *slot =
host->current_slot;
- dev_err(mmc_dev(host->mmc),
- "command timeout, CMD %d\n",
- host->cmd->opcode);
+ if (!mmc_omap_cover_is_open(slot))
+ dev_err(mmc_dev(host->mmc),
+ "command timeout, CMD %d\n",
+ host->cmd->opcode);
host->cmd->error = -ETIMEDOUT;
end_command = 1;
}
@@ -592,6 +616,42 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+void omap_mmc_notify_cover_event(struct device *dev, int slot, int is_closed)
+{
+ struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+ BUG_ON(slot >= host->nr_slots);
+
+ /* Other subsystems can call in here before we're initialised. */
+ if (host->nr_slots == 0 || !host->slots[slot])
+ return;
+
+ schedule_work(&host->slots[slot]->switch_work);
+}
+
+static void mmc_omap_switch_timer(unsigned long arg)
+{
+ struct mmc_omap_slot *slot = (struct mmc_omap_slot *) arg;
+
+ schedule_work(&slot->switch_work);
+}
+
+static void mmc_omap_cover_handler(struct work_struct *work)
+{
+ struct mmc_omap_slot *slot = container_of(work, struct mmc_omap_slot,
+ switch_work);
+ int cover_open;
+
+ cover_open = mmc_omap_cover_is_open(slot);
+ if (cover_open != slot->cover_open) {
+ sysfs_notify(&slot->mmc->class_dev.kobj, NULL, "cover_switch");
+ slot->cover_open = cover_open;
+ dev_info(mmc_dev(slot->mmc), "cover is now %s\n",
+ cover_open ? "open" : "closed");
+ }
+ mmc_detect_change(slot->mmc, slot->id);
+}
+
/* Prepare to transfer the next segment of a scatterlist */
static void
mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
@@ -1072,13 +1132,34 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id)
goto err_remove_host;
}
+ if (slot->pdata->get_cover_state != NULL) {
+ r = device_create_file(&mmc->class_dev,
+ &dev_attr_cover_switch);
+ if (r < 0)
+ goto err_remove_slot_name;
+
+ INIT_WORK(&slot->switch_work, mmc_omap_cover_handler);
+ init_timer(&slot->switch_timer);
+ slot->switch_timer.function = mmc_omap_switch_timer;
+ slot->switch_timer.data = (unsigned long) slot;
+ schedule_work(&slot->switch_work);
+ }
+
if (slot->pdata->get_ro != NULL) {
r = device_create_file(&mmc->class_dev,
&dev_attr_ro);
+ if (r < 0)
+ goto err_remove_cover_attr;
}
return 0;
+err_remove_cover_attr:
+ if (slot->pdata->get_cover_state != NULL)
+ device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
+err_remove_slot_name:
+ if (slot->pdata->name != NULL)
+ device_remove_file(&mmc->class_dev, &dev_attr_ro);
err_remove_host:
mmc_remove_host(mmc);
mmc_free_host(mmc);
@@ -1091,9 +1172,14 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot)
if (slot->pdata->name != NULL)
device_remove_file(&mmc->class_dev, &dev_attr_slot_name);
+ if (slot->pdata->get_cover_state != NULL)
+ device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
if (slot->pdata->get_ro != NULL)
device_remove_file(&mmc->class_dev, &dev_attr_ro);
+ del_timer_sync(&slot->switch_timer);
+ flush_scheduled_work();
+
mmc_remove_host(mmc);
mmc_free_host(mmc);
}
-- 1.5.3.GIT
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 00/18] MMC: OMAP: Sync MMC OMAP driver with mainline tree
@ 2008-03-14 19:35 Carlos Aguiar
2008-03-24 12:26 ` Pierre Ossman
0 siblings, 1 reply; 3+ messages in thread
From: Carlos Aguiar @ 2008-03-14 19:35 UTC (permalink / raw)
To: Pierre Ossman; +Cc: Tony Lindgren, linux-kernel
Hi Pierre, Tony and folks,
The new version of the patch series that follows is a synchronization
of MMC OMAP driver from Linux-OMAP tree into mainline tree.
Improvements and corrections are based on comments from Pierre Ossman and
Roel Kluin, from LKML.
Just to remind you, basically it brings MMC multislot support for OMAP boards
with one slot (like H2 1611, H3 1710) or two slots (like H4 2420 and N800).
Others boards supported by such feature are: N770, Siemens SX1 and Apollon.
BR,
Carlos.
--
Carlos Eduardo Aguiar
Nokia Institute of Technology - INdT
Open Source Mobile Research Center - OSMRC - Manaus
Core Team
Phone: +55 92 2126-1079
Mobile: +55 92 8127-1797
E-mail: carlos.aguiar@indt.org.br
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 00/18] MMC: OMAP: Sync MMC OMAP driver with mainline tree
2008-03-14 19:35 [PATCH 00/18] MMC: OMAP: Sync MMC OMAP driver with mainline tree Carlos Aguiar
@ 2008-03-24 12:26 ` Pierre Ossman
2008-03-26 20:09 ` [PATCH 06/18] MMC: OMAP: Add back cover switch support Carlos Aguiar
0 siblings, 1 reply; 3+ messages in thread
From: Pierre Ossman @ 2008-03-24 12:26 UTC (permalink / raw)
To: Carlos Aguiar; +Cc: Tony Lindgren, linux-kernel
On Fri, 14 Mar 2008 15:35:56 -0400
Carlos Aguiar <carlos.aguiar@indt.org.br> wrote:
Except for the issue with the device attributes, the patch set looks fine. Send me a fix for that patch (and affected subsequent) and I'll queue it up.
--
-- Pierre Ossman
Linux kernel, MMC maintainer http://www.kernel.org
PulseAudio, core developer http://pulseaudio.org
rdesktop, core developer http://www.rdesktop.org
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH 06/18] MMC: OMAP: Add back cover switch support
2008-03-24 12:26 ` Pierre Ossman
@ 2008-03-26 20:09 ` Carlos Aguiar
0 siblings, 0 replies; 3+ messages in thread
From: Carlos Aguiar @ 2008-03-26 20:09 UTC (permalink / raw)
To: ext Pierre Ossman; +Cc: Tony Lindgren, linux-kernel
From: Juha Yrjola <juha.yrjola@solidboot.com>
This patch adds back MMC cover switch support in a way that
supports multiple slots.
Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Signed-off-by: Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/mmc/host/omap.c | 87 +++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 84 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 6b4f040..fc46a70 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -106,6 +106,10 @@ struct mmc_omap_slot {
unsigned int fclk_freq;
unsigned powered:1;
+ struct work_struct switch_work;
+ struct timer_list switch_timer;
+ unsigned cover_open;
+
struct mmc_request *mrq;
struct mmc_omap_host *host;
struct mmc_host *mmc;
@@ -226,6 +230,25 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot)
spin_unlock_irqrestore(&host->slot_lock, flags);
}
+static inline
+int mmc_omap_cover_is_open(struct mmc_omap_slot *slot)
+{
+ return slot->pdata->get_cover_state(mmc_dev(slot->mmc), slot->id);
+}
+
+static ssize_t
+mmc_omap_show_cover_switch(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
+ struct mmc_omap_slot *slot = mmc_priv(mmc);
+
+ return sprintf(buf, "%s\n", mmc_omap_cover_is_open(slot) ? "open" :
+ "closed");
+}
+
+static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
+
static ssize_t
mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -544,9 +567,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
if (host->cmd) {
struct mmc_omap_slot *slot =
host->current_slot;
- dev_err(mmc_dev(host->mmc),
- "command timeout, CMD %d\n",
- host->cmd->opcode);
+ if (!mmc_omap_cover_is_open(slot))
+ dev_err(mmc_dev(host->mmc),
+ "command timeout, CMD %d\n",
+ host->cmd->opcode);
host->cmd->error = -ETIMEDOUT;
end_command = 1;
}
@@ -592,6 +616,42 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+void omap_mmc_notify_cover_event(struct device *dev, int slot, int is_closed)
+{
+ struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+ BUG_ON(slot >= host->nr_slots);
+
+ /* Other subsystems can call in here before we're initialised. */
+ if (host->nr_slots == 0 || !host->slots[slot])
+ return;
+
+ schedule_work(&host->slots[slot]->switch_work);
+}
+
+static void mmc_omap_switch_timer(unsigned long arg)
+{
+ struct mmc_omap_slot *slot = (struct mmc_omap_slot *) arg;
+
+ schedule_work(&slot->switch_work);
+}
+
+static void mmc_omap_cover_handler(struct work_struct *work)
+{
+ struct mmc_omap_slot *slot = container_of(work, struct mmc_omap_slot,
+ switch_work);
+ int cover_open;
+
+ cover_open = mmc_omap_cover_is_open(slot);
+ if (cover_open != slot->cover_open) {
+ sysfs_notify(&slot->mmc->class_dev.kobj, NULL, "cover_switch");
+ slot->cover_open = cover_open;
+ dev_info(mmc_dev(slot->mmc), "cover is now %s\n",
+ cover_open ? "open" : "closed");
+ }
+ mmc_detect_change(slot->mmc, slot->id);
+}
+
/* Prepare to transfer the next segment of a scatterlist */
static void
mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
@@ -1062,8 +1122,24 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id)
goto err_remove_host;
}
+ if (slot->pdata->get_cover_state != NULL) {
+ r = device_create_file(&mmc->class_dev,
+ &dev_attr_cover_switch);
+ if (r < 0)
+ goto err_remove_slot_name;
+
+ INIT_WORK(&slot->switch_work, mmc_omap_cover_handler);
+ init_timer(&slot->switch_timer);
+ slot->switch_timer.function = mmc_omap_switch_timer;
+ slot->switch_timer.data = (unsigned long) slot;
+ schedule_work(&slot->switch_work);
+ }
+
return 0;
+err_remove_slot_name:
+ if (slot->pdata->name != NULL)
+ device_remove_file(&mmc->class_dev, &dev_attr_slot_name);
err_remove_host:
mmc_remove_host(mmc);
mmc_free_host(mmc);
@@ -1076,6 +1152,11 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot)
if (slot->pdata->name != NULL)
device_remove_file(&mmc->class_dev, &dev_attr_slot_name);
+ if (slot->pdata->get_cover_state != NULL)
+ device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
+
+ del_timer_sync(&slot->switch_timer);
+ flush_scheduled_work();
mmc_remove_host(mmc);
mmc_free_host(mmc);
-- 1.5.3.GIT
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 06/18] MMC: OMAP: Add back cover switch support
@ 2008-01-28 19:07 Carlos Aguiar
0 siblings, 0 replies; 3+ messages in thread
From: Carlos Aguiar @ 2008-01-28 19:07 UTC (permalink / raw)
To: Pierre Ossman; +Cc: Tony Lindgren, linux-kernel
From: Juha Yrjola <juha.yrjola@solidboot.com>
This patch adds back MMC cover switch support in a way that
supports multiple slots.
Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Signed-off-by: Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/mmc/host/omap.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 84 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 35719e7..c6dac7e 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -107,6 +107,10 @@ struct mmc_omap_slot {
unsigned int fclk_freq;
unsigned powered:1;
+ struct work_struct switch_work;
+ struct timer_list switch_timer;
+ unsigned cover_open;
+
struct mmc_request *mrq;
struct mmc_omap_host *host;
struct mmc_host *mmc;
@@ -227,6 +231,25 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot)
spin_unlock_irqrestore(&host->slot_lock, flags);
}
+static inline
+int mmc_omap_cover_is_open(struct mmc_omap_slot *slot)
+{
+ return slot->pdata->get_cover_state(mmc_dev(slot->mmc), slot->id);
+}
+
+static ssize_t
+mmc_omap_show_cover_switch(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
+ struct mmc_omap_slot *slot = mmc_priv(mmc);
+
+ return sprintf(buf, "%s\n", mmc_omap_cover_is_open(slot) ? "open" :
+ "closed");
+}
+
+static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
+
/* Access to the R/O switch is required for production testing
* purposes. */
static ssize_t
@@ -563,7 +586,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
host->cmd->opcode !=
MMC_SEND_OP_COND &&
host->cmd->opcode !=
- MMC_APP_CMD)
+ MMC_APP_CMD &&
+ !mmc_omap_cover_is_open(slot))
dev_err(mmc_dev(host->mmc),
"command timeout, CMD %d\n",
host->cmd->opcode);
@@ -612,6 +636,42 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+void omap_mmc_notify_cover_event(struct device *dev, int slot, int is_closed)
+{
+ struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+ BUG_ON(slot >= host->nr_slots);
+
+ /* Other subsystems can call in here before we're initialised. */
+ if (host->nr_slots == 0 || !host->slots[slot])
+ return;
+
+ schedule_work(&host->slots[slot]->switch_work);
+}
+
+static void mmc_omap_switch_timer(unsigned long arg)
+{
+ struct mmc_omap_slot *slot = (struct mmc_omap_slot *) arg;
+
+ schedule_work(&slot->switch_work);
+}
+
+static void mmc_omap_cover_handler(struct work_struct *work)
+{
+ struct mmc_omap_slot *slot = container_of(work, struct mmc_omap_slot,
+ switch_work);
+ int cover_open;
+
+ cover_open = mmc_omap_cover_is_open(slot);
+ if (cover_open != slot->cover_open) {
+ sysfs_notify(&slot->mmc->class_dev.kobj, NULL, "cover_switch");
+ slot->cover_open = cover_open;
+ dev_info(mmc_dev(slot->mmc), "cover is now %s\n",
+ cover_open ? "open" : "closed");
+ }
+ mmc_detect_change(slot->mmc, slot->id);
+}
+
/* Prepare to transfer the next segment of a scatterlist */
static void
mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
@@ -1093,13 +1153,31 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id)
goto err_remove_host;
}
+ if (slot->pdata->get_cover_state != NULL) {
+ r = device_create_file(&mmc->class_dev,
+ &dev_attr_cover_switch);
+ if (r < 0)
+ goto err_remove_slot_name;
+
+ INIT_WORK(&slot->switch_work, mmc_omap_cover_handler);
+ init_timer(&slot->switch_timer);
+ slot->switch_timer.function = mmc_omap_switch_timer;
+ slot->switch_timer.data = (unsigned long) slot;
+ schedule_work(&slot->switch_work);
+ }
+
if (slot->pdata->get_ro != NULL) {
r = device_create_file(&mmc->class_dev,
&dev_attr_ro);
+ if (r < 0)
+ goto err_remove_cover_attr;
}
return 0;
+err_remove_cover_attr:
+ if (slot->pdata->get_cover_state != NULL)
+ device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
err_remove_slot_name:
if (slot->pdata->name != NULL)
device_remove_file(&mmc->class_dev, &dev_attr_ro);
@@ -1114,9 +1192,14 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot)
if (slot->pdata->name != NULL)
device_remove_file(&mmc->class_dev, &dev_attr_slot_name);
+ if (slot->pdata->get_cover_state != NULL)
+ device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
if (slot->pdata->get_ro != NULL)
device_remove_file(&mmc->class_dev, &dev_attr_ro);
+ del_timer_sync(&slot->switch_timer);
+ flush_scheduled_work();
+
mmc_remove_host(mmc);
mmc_free_host(mmc);
}
-- 1.5.3.GIT
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-03-26 20:14 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-14 19:36 [PATCH 06/18] MMC: OMAP: Add back cover switch support Carlos Aguiar
-- strict thread matches above, loose matches on Subject: below --
2008-03-14 19:35 [PATCH 00/18] MMC: OMAP: Sync MMC OMAP driver with mainline tree Carlos Aguiar
2008-03-24 12:26 ` Pierre Ossman
2008-03-26 20:09 ` [PATCH 06/18] MMC: OMAP: Add back cover switch support Carlos Aguiar
2008-01-28 19:07 Carlos Aguiar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox