diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2011-02-02 08:41:19 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2011-03-14 09:05:12 -0400 |
commit | 1a721859f8e57ddf3f6df2b5094057f9f536b4d0 (patch) | |
tree | b8d15cc4e560c3657f62147d2873958c6f410552 | |
parent | 741caea4e518f5374cc9ff7cfaabc0e591416420 (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.c | 148 |
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 | ||
28 | struct mmci_card_event { | 23 | static 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 | ||
35 | static 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 | |||
44 | static 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 | |||
55 | static 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 | |||
66 | static DEVICE_ATTR(mmc_inserted, S_IRUGO, gpio_show, NULL); | ||
67 | |||
68 | static 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 | |||
89 | int __devinit mmc_init(struct amba_device *adev) | 37 | int __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"); | ||
180 | out: | ||
181 | return ret; | 59 | return ret; |
182 | } | 60 | } |