aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2011-02-02 08:41:19 -0500
committerLinus Walleij <linus.walleij@linaro.org>2011-03-14 09:05:12 -0400
commit1a721859f8e57ddf3f6df2b5094057f9f536b4d0 (patch)
treeb8d15cc4e560c3657f62147d2873958c6f410552
parent741caea4e518f5374cc9ff7cfaabc0e591416420 (diff)
mach-u300: use mmci driver for GPIO card detect
The mmci driver can handle a GPIO pin for card detect, using IRQs and all just fine, so switch to using that. Delete the old bogus input device hack, if userspace need to detect MMC cards it should use udev like everyone else. Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--arch/arm/mach-u300/mmc.c148
1 files changed, 13 insertions, 135 deletions
diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c
index de1ac9ad2213..8bb4ef42ab04 100644
--- a/arch/arm/mach-u300/mmc.c
+++ b/arch/arm/mach-u300/mmc.c
@@ -13,11 +13,6 @@
13#include <linux/device.h> 13#include <linux/device.h>
14#include <linux/amba/bus.h> 14#include <linux/amba/bus.h>
15#include <linux/mmc/host.h> 15#include <linux/mmc/host.h>
16#include <linux/input.h>
17#include <linux/workqueue.h>
18#include <linux/delay.h>
19#include <linux/regulator/consumer.h>
20#include <linux/regulator/machine.h>
21#include <linux/gpio.h> 16#include <linux/gpio.h>
22#include <linux/amba/mmci.h> 17#include <linux/amba/mmci.h>
23#include <linux/slab.h> 18#include <linux/slab.h>
@@ -25,137 +20,27 @@
25#include "mmc.h" 20#include "mmc.h"
26#include "padmux.h" 21#include "padmux.h"
27 22
28struct mmci_card_event { 23static struct mmci_platform_data mmc0_plat_data = {
29 struct input_dev *mmc_input; 24 /*
30 int mmc_inserted; 25 * Do not set ocr_mask or voltage translation function,
31 struct work_struct workq; 26 * we have a regulator we can control instead.
32 struct mmci_platform_data mmc0_plat_data; 27 */
28 /* Nominally 2.85V on our platform */
29 .f_max = 24000000,
30 .gpio_wp = -1,
31 .gpio_cd = U300_GPIO_PIN_MMC_CD,
32 .cd_invert = true,
33 .capabilities = MMC_CAP_MMC_HIGHSPEED |
34 MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
33}; 35};
34 36
35static unsigned int mmc_status(struct device *dev)
36{
37 struct mmci_card_event *mmci_card = container_of(
38 dev->platform_data,
39 struct mmci_card_event, mmc0_plat_data);
40
41 return mmci_card->mmc_inserted;
42}
43
44static int mmci_callback(void *data)
45{
46 struct mmci_card_event *mmci_card = data;
47
48 disable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD);
49 schedule_work(&mmci_card->workq);
50
51 return 0;
52}
53
54
55static ssize_t gpio_show(struct device *dev, struct device_attribute *attr,
56 char *buf)
57{
58 struct mmci_card_event *mmci_card = container_of(
59 dev->platform_data,
60 struct mmci_card_event, mmc0_plat_data);
61
62
63 return sprintf(buf, "%d\n", !mmci_card->mmc_inserted);
64}
65
66static DEVICE_ATTR(mmc_inserted, S_IRUGO, gpio_show, NULL);
67
68static void _mmci_callback(struct work_struct *ws)
69{
70
71 struct mmci_card_event *mmci_card = container_of(
72 ws,
73 struct mmci_card_event, workq);
74
75 mdelay(20);
76
77 mmci_card->mmc_inserted = !gpio_get_value(U300_GPIO_PIN_MMC_CD);
78
79 input_report_switch(mmci_card->mmc_input, KEY_INSERT,
80 mmci_card->mmc_inserted);
81 input_sync(mmci_card->mmc_input);
82
83 pr_debug("MMC/SD card was %s\n",
84 mmci_card->mmc_inserted ? "inserted" : "removed");
85
86 enable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD, mmci_card->mmc_inserted);
87}
88
89int __devinit mmc_init(struct amba_device *adev) 37int __devinit mmc_init(struct amba_device *adev)
90{ 38{
91 struct mmci_card_event *mmci_card;
92 struct device *mmcsd_device = &adev->dev; 39 struct device *mmcsd_device = &adev->dev;
93 struct pmx *pmx; 40 struct pmx *pmx;
94 int ret = 0; 41 int ret = 0;
95 42
96 mmci_card = kzalloc(sizeof(struct mmci_card_event), GFP_KERNEL); 43 mmcsd_device->platform_data = &mmc0_plat_data;
97 if (!mmci_card)
98 return -ENOMEM;
99
100 /*
101 * Do not set ocr_mask or voltage translation function,
102 * we have a regulator we can control instead.
103 */
104 /* Nominally 2.85V on our platform */
105 mmci_card->mmc0_plat_data.f_max = 24000000;
106 mmci_card->mmc0_plat_data.status = mmc_status;
107 mmci_card->mmc0_plat_data.gpio_wp = -1;
108 mmci_card->mmc0_plat_data.gpio_cd = -1;
109 mmci_card->mmc0_plat_data.capabilities = MMC_CAP_MMC_HIGHSPEED |
110 MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
111
112 mmcsd_device->platform_data = (void *) &mmci_card->mmc0_plat_data;
113
114 INIT_WORK(&mmci_card->workq, _mmci_callback);
115
116 ret = gpio_request(U300_GPIO_PIN_MMC_CD, "MMC card detection");
117 if (ret) {
118 printk(KERN_CRIT "Could not allocate MMC card detection " \
119 "GPIO pin\n");
120 goto out;
121 }
122
123 ret = gpio_direction_input(U300_GPIO_PIN_MMC_CD);
124 if (ret) {
125 printk(KERN_CRIT "Invalid GPIO pin requested\n");
126 goto out;
127 }
128
129 ret = sysfs_create_file(&mmcsd_device->kobj,
130 &dev_attr_mmc_inserted.attr);
131 if (ret)
132 goto out;
133
134 mmci_card->mmc_input = input_allocate_device();
135 if (!mmci_card->mmc_input) {
136 printk(KERN_CRIT "Could not allocate MMC input device\n");
137 return -ENOMEM;
138 }
139
140 mmci_card->mmc_input->name = "MMC insert notification";
141 mmci_card->mmc_input->id.bustype = BUS_HOST;
142 mmci_card->mmc_input->id.vendor = 0;
143 mmci_card->mmc_input->id.product = 0;
144 mmci_card->mmc_input->id.version = 0x0100;
145 mmci_card->mmc_input->dev.parent = mmcsd_device;
146 input_set_capability(mmci_card->mmc_input, EV_SW, KEY_INSERT);
147
148 /*
149 * Since this must always be compiled into the kernel, this input
150 * is never unregistered or free:ed.
151 */
152 ret = input_register_device(mmci_card->mmc_input);
153 if (ret) {
154 input_free_device(mmci_card->mmc_input);
155 goto out;
156 }
157
158 input_set_drvdata(mmci_card->mmc_input, mmci_card);
159 44
160 /* 45 /*
161 * Setup padmuxing for MMC. Since this must always be 46 * Setup padmuxing for MMC. Since this must always be
@@ -171,12 +56,5 @@ int __devinit mmc_init(struct amba_device *adev)
171 pr_warning("Could not activate padmuxing\n"); 56 pr_warning("Could not activate padmuxing\n");
172 } 57 }
173 58
174 ret = gpio_register_callback(U300_GPIO_PIN_MMC_CD, mmci_callback,
175 mmci_card);
176
177 schedule_work(&mmci_card->workq);
178
179 printk(KERN_INFO "Registered MMC insert/remove notification\n");
180out:
181 return ret; 59 return ret;
182} 60}