diff options
author | David Brownell <david-b@pacbell.net> | 2005-11-01 14:44:30 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2005-11-01 14:44:30 -0500 |
commit | 85eb226c446a017996859093cbfb5d3ae2c2117a (patch) | |
tree | 383325e8da1f589ade1236017df896fb06bfab14 /arch | |
parent | 4ebc3364de368c92138e740f6c9050c93a2f0c3c (diff) |
[ARM] 3078/1: lubbock platform updates, mostly mmc detection
Patch from David Brownell
Lubbock updates:
* Provide an address for the SMC91x chip that doesn't generate
a boot-time warning (matching the EEPROM).
* Update MMC support to (a) detect card insert/remove, and
(b) report the readonly switch setting for SD cards.
Previously, MMC/SD cards had to be present at boot time else they
couldn't be detected.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-pxa/lubbock.c | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index beccf455f796..689f31349bd6 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c | |||
@@ -175,7 +175,7 @@ static struct platform_device sa1111_device = { | |||
175 | static struct resource smc91x_resources[] = { | 175 | static struct resource smc91x_resources[] = { |
176 | [0] = { | 176 | [0] = { |
177 | .name = "smc91x-regs", | 177 | .name = "smc91x-regs", |
178 | .start = 0x0c000000, | 178 | .start = 0x0c000c00, |
179 | .end = 0x0c0fffff, | 179 | .end = 0x0c0fffff, |
180 | .flags = IORESOURCE_MEM, | 180 | .flags = IORESOURCE_MEM, |
181 | }, | 181 | }, |
@@ -224,18 +224,75 @@ static struct pxafb_mach_info sharp_lm8v31 __initdata = { | |||
224 | .lccr3 = LCCR3_PCP | LCCR3_Acb(255), | 224 | .lccr3 = LCCR3_PCP | LCCR3_Acb(255), |
225 | }; | 225 | }; |
226 | 226 | ||
227 | static int lubbock_mci_init(struct device *dev, irqreturn_t (*lubbock_detect_int)(int, void *, struct pt_regs *), void *data) | 227 | #define MMC_POLL_RATE msecs_to_jiffies(1000) |
228 | |||
229 | static void lubbock_mmc_poll(unsigned long); | ||
230 | static irqreturn_t (*mmc_detect_int)(int, void *, struct pt_regs *); | ||
231 | |||
232 | static struct timer_list mmc_timer = { | ||
233 | .function = lubbock_mmc_poll, | ||
234 | }; | ||
235 | |||
236 | static void lubbock_mmc_poll(unsigned long data) | ||
237 | { | ||
238 | unsigned long flags; | ||
239 | |||
240 | /* clear any previous irq state, then ... */ | ||
241 | local_irq_save(flags); | ||
242 | LUB_IRQ_SET_CLR &= ~(1 << 0); | ||
243 | local_irq_restore(flags); | ||
244 | |||
245 | /* poll until mmc/sd card is removed */ | ||
246 | if (LUB_IRQ_SET_CLR & (1 << 0)) | ||
247 | mod_timer(&mmc_timer, jiffies + MMC_POLL_RATE); | ||
248 | else { | ||
249 | (void) mmc_detect_int(LUBBOCK_SD_IRQ, (void *)data, NULL); | ||
250 | enable_irq(LUBBOCK_SD_IRQ); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | static irqreturn_t lubbock_detect_int(int irq, void *data, struct pt_regs *regs) | ||
255 | { | ||
256 | /* IRQ is level triggered; disable, and poll for removal */ | ||
257 | disable_irq(irq); | ||
258 | mod_timer(&mmc_timer, jiffies + MMC_POLL_RATE); | ||
259 | |||
260 | return mmc_detect_int(irq, data, regs); | ||
261 | } | ||
262 | |||
263 | static int lubbock_mci_init(struct device *dev, | ||
264 | irqreturn_t (*detect_int)(int, void *, struct pt_regs *), | ||
265 | void *data) | ||
228 | { | 266 | { |
229 | /* setup GPIO for PXA25x MMC controller */ | 267 | /* setup GPIO for PXA25x MMC controller */ |
230 | pxa_gpio_mode(GPIO6_MMCCLK_MD); | 268 | pxa_gpio_mode(GPIO6_MMCCLK_MD); |
231 | pxa_gpio_mode(GPIO8_MMCCS0_MD); | 269 | pxa_gpio_mode(GPIO8_MMCCS0_MD); |
232 | 270 | ||
233 | return 0; | 271 | /* detect card insert/eject */ |
272 | mmc_detect_int = detect_int; | ||
273 | init_timer(&mmc_timer); | ||
274 | mmc_timer.data = (unsigned long) data; | ||
275 | return request_irq(LUBBOCK_SD_IRQ, lubbock_detect_int, | ||
276 | SA_SAMPLE_RANDOM, "lubbock-sd-detect", data); | ||
277 | } | ||
278 | |||
279 | static int lubbock_mci_get_ro(struct device *dev) | ||
280 | { | ||
281 | return (LUB_MISC_RD & (1 << 2)) != 0; | ||
282 | } | ||
283 | |||
284 | static void lubbock_mci_exit(struct device *dev, void *data) | ||
285 | { | ||
286 | free_irq(LUBBOCK_SD_IRQ, data); | ||
287 | del_timer_sync(&mmc_timer); | ||
234 | } | 288 | } |
235 | 289 | ||
236 | static struct pxamci_platform_data lubbock_mci_platform_data = { | 290 | static struct pxamci_platform_data lubbock_mci_platform_data = { |
237 | .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, | 291 | .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, |
292 | .detect_delay = 1, | ||
238 | .init = lubbock_mci_init, | 293 | .init = lubbock_mci_init, |
294 | .get_ro = lubbock_mci_get_ro, | ||
295 | .exit = lubbock_mci_exit, | ||
239 | }; | 296 | }; |
240 | 297 | ||
241 | static void lubbock_irda_transceiver_mode(struct device *dev, int mode) | 298 | static void lubbock_irda_transceiver_mode(struct device *dev, int mode) |