diff options
Diffstat (limited to 'recipes/linux/gumstix-kernel-2.6.21/compact-flash.patch')
-rw-r--r-- | recipes/linux/gumstix-kernel-2.6.21/compact-flash.patch | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/recipes/linux/gumstix-kernel-2.6.21/compact-flash.patch b/recipes/linux/gumstix-kernel-2.6.21/compact-flash.patch new file mode 100644 index 0000000000..e3bce37c85 --- /dev/null +++ b/recipes/linux/gumstix-kernel-2.6.21/compact-flash.patch @@ -0,0 +1,287 @@ +Index: linux-2.6.21gum/drivers/pcmcia/Makefile +=================================================================== +--- linux-2.6.21gum.orig/drivers/pcmcia/Makefile ++++ linux-2.6.21gum/drivers/pcmcia/Makefile +@@ -69,4 +69,4 @@ sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa + pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o + pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o + pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o +- ++pxa2xx_cs-$(CONFIG_ARCH_GUMSTIX) += pxa2xx_gumstix.o +Index: linux-2.6.21gum/drivers/pcmcia/pxa2xx_gumstix.c +=================================================================== +--- /dev/null ++++ linux-2.6.21gum/drivers/pcmcia/pxa2xx_gumstix.c +@@ -0,0 +1,272 @@ ++/* ++ * linux/drivers/pcmcia/pxa2xx_gumstix.c ++ * ++ * Gumstix PCMCIA specific routines. Based on Mainstone ++ * ++ * Copyright 2004, Craig Hughes <craig@gumstix.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/errno.h> ++#include <linux/interrupt.h> ++#include <linux/device.h> ++#include <linux/platform_device.h> ++ ++#include <pcmcia/ss.h> ++ ++#include <asm/hardware.h> ++#include <asm/delay.h> ++#include <asm/arch/pxa-regs.h> ++#include <asm/irq.h> ++#include <asm/io.h> ++ ++#include <asm/arch/gumstix.h> ++ ++#include "soc_common.h" ++ ++static struct pcmcia_irqs gumstix_pcmcia_irqs0[] = { ++ { 0, GUMSTIX_S0_nCD_IRQ, "CF0 nCD" }, ++ { 0, GUMSTIX_S0_nSTSCHG_IRQ, "CF0 nSTSCHG" }, ++}; ++ ++static struct pcmcia_irqs gumstix_pcmcia_irqs1[] = { ++ { 1, GUMSTIX_S1_nCD_IRQ, "CF1 nCD" }, ++ { 1, GUMSTIX_S1_nSTSCHG_IRQ, "CF1 nSTSCHG" }, ++}; ++ ++static int net_cf_vx_mode = 0; ++ ++static int gumstix_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ++{ ++ if(skt->nr == 0) ++ { ++ pxa_gpio_mode(GPIO_GUMSTIX_nSTSCHG_0_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_nCD_0_MD); ++ if(net_cf_vx_mode) ++ pxa_gpio_mode(GPIO_GUMSTIX_PRDY_nBSY_0_OLD_MD); ++ else ++ pxa_gpio_mode(GPIO_GUMSTIX_PRDY_nBSY_0_MD); ++ } else { ++ pxa_gpio_mode(GPIO_GUMSTIX_nSTSCHG_1_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_nCD_1_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_PRDY_nBSY_1_MD); ++ } ++ ++ pxa_gpio_mode(GPIO_GUMSTIX_nPOE_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_nPWE_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_nPIOR_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_nPIOW_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_nPCE_1_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_nPCE_2_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_pSKTSEL_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_nPREG_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_nPWAIT_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_nIOIS16_MD); ++ ++ skt->irq = (skt->nr == 0) ? ((net_cf_vx_mode == 0) ? GUMSTIX_S0_PRDY_nBSY_IRQ : GUMSTIX_S0_PRDY_nBSY_OLD_IRQ) : GUMSTIX_S1_PRDY_nBSY_IRQ; ++ ++ return (skt->nr == 0) ? soc_pcmcia_request_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0)) : ++ soc_pcmcia_request_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1)); ++} ++ ++static void gumstix_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) ++{ ++ if(skt->nr == 0) ++ { ++ soc_pcmcia_free_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0)); ++ } else { ++ soc_pcmcia_free_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1)); ++ } ++} ++ ++static void gumstix_pcmcia_socket_state(struct soc_pcmcia_socket *skt, ++ struct pcmcia_state *state) ++{ ++ unsigned int cd, prdy_nbsy, nbvd1; ++ if(skt->nr == 0) ++ { ++ cd = GPIO_GUMSTIX_nCD_0; ++ if(net_cf_vx_mode) ++ prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_0_OLD; ++ else ++ prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_0; ++ nbvd1 = GPIO_GUMSTIX_nBVD1_0; ++ } else { ++ cd = GPIO_GUMSTIX_nCD_1; ++ prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_1; ++ nbvd1 = GPIO_GUMSTIX_nBVD1_1; ++ } ++ state->detect = !(GPLR(cd) & GPIO_bit(cd)); ++ state->ready = !!(GPLR(prdy_nbsy) & GPIO_bit(prdy_nbsy)); ++ state->bvd1 = !!(GPLR(nbvd1) & GPIO_bit(nbvd1)); ++ state->bvd2 = 1; ++ state->vs_3v = 0; ++ state->vs_Xv = 0; ++ state->wrprot = 0; ++} ++ ++static int gumstix_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, ++ const socket_state_t *state) ++{ ++ return 0; ++} ++ ++static void gumstix_pcmcia_socket_init(struct soc_pcmcia_socket *skt) ++{ ++ if(skt->nr) { ++ soc_pcmcia_enable_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0)); ++ } else { ++ soc_pcmcia_enable_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1)); ++ } ++} ++ ++static void gumstix_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) ++{ ++ if(skt->nr) { ++ soc_pcmcia_disable_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0)); ++ } else { ++ soc_pcmcia_disable_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1)); ++ } ++} ++ ++static struct pcmcia_low_level gumstix_pcmcia_ops = { ++ .owner = THIS_MODULE, ++ .hw_init = gumstix_pcmcia_hw_init, ++ .hw_shutdown = gumstix_pcmcia_hw_shutdown, ++ .socket_state = gumstix_pcmcia_socket_state, ++ .configure_socket = gumstix_pcmcia_configure_socket, ++ .socket_init = gumstix_pcmcia_socket_init, ++ .socket_suspend = gumstix_pcmcia_socket_suspend, ++ .nr = 2, ++}; ++ ++static struct platform_device *gumstix_pcmcia_device; ++ ++inline void __init gumstix_pcmcia_cpld_clk(void) ++{ ++ GPCR(GPIO_GUMSTIX_nPOE) = GPIO_bit(GPIO_GUMSTIX_nPOE); ++ GPSR(GPIO_GUMSTIX_nPOE) = GPIO_bit(GPIO_GUMSTIX_nPOE); ++} ++ ++inline unsigned char __init gumstix_pcmcia_cpld_read_bits(int bits) ++{ ++ unsigned char result = 0; ++ unsigned int shift = 0; ++ while(bits--) ++ { ++ result |= !!(GPLR(GPIO_GUMSTIX_nCD_0) & GPIO_bit(GPIO_GUMSTIX_nCD_0)) << shift; ++ shift ++; ++ gumstix_pcmcia_cpld_clk(); ++ } ++ printk("CPLD responded with: %02x\n",result); ++ return result; ++} ++ ++/* We use the CPLD on the CF-CF card to read a value from a shift register. If we can read that ++ * magic sequence, then we have 2 CF cards; otherwise we assume just one ++ * The CPLD will send the value of the shift register on GPIO11 (the CD line for slot 0) ++ * when RESET is held in reset. We use GPIO48 (nPOE) as a clock signal, ++ * GPIO52/53 (card enable for both cards) to control read/write to the shift register ++ */ ++static void __init gumstix_count_cards(void) ++{ ++ pxa_gpio_mode(GPIO_GUMSTIX_nPOE | GPIO_OUT); ++ pxa_gpio_mode(GPIO_GUMSTIX_nPCE_1 | GPIO_OUT); ++ pxa_gpio_mode(GPIO_GUMSTIX_nPCE_2 | GPIO_OUT); ++ pxa_gpio_mode(GPIO_GUMSTIX_nCD_0 | GPIO_IN); ++ if(net_cf_vx_mode) ++ pxa_gpio_mode(GPIO_GUMSTIX_CF_OLD_RESET | GPIO_OUT); ++ else ++ pxa_gpio_mode(GPIO_GUMSTIX_CF_RESET | GPIO_OUT); ++ ++ // Enter reset ++ if(net_cf_vx_mode) ++ GPSR(GPIO_GUMSTIX_CF_OLD_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_OLD_RESET); ++ else ++ GPSR(GPIO_GUMSTIX_CF_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_RESET); ++ ++ // Setup the shift register ++ GPSR(GPIO_GUMSTIX_nPCE_1) = GPIO_bit(GPIO_GUMSTIX_nPCE_1); ++ GPCR(GPIO_GUMSTIX_nPCE_2) = GPIO_bit(GPIO_GUMSTIX_nPCE_2); ++ ++ // Tick the clock to program the shift register ++ gumstix_pcmcia_cpld_clk(); ++ ++ // Now set shift register into read mode ++ GPCR(GPIO_GUMSTIX_nPCE_1) = GPIO_bit(GPIO_GUMSTIX_nPCE_1); ++ GPSR(GPIO_GUMSTIX_nPCE_2) = GPIO_bit(GPIO_GUMSTIX_nPCE_2); ++ ++ // We can read the bits now -- 0xC2 means "Dual compact flash" ++ if(gumstix_pcmcia_cpld_read_bits(8) != 0xC2) ++ { ++ // We do not have 2 CF slots ++ gumstix_pcmcia_ops.nr = 1; ++ } ++} ++ ++#ifdef CONFIG_ARCH_GUMSTIX_VERDEX ++static void __init gumstix_check_if_netCF_vx(void) ++{ ++ void *network_controller_memory = ioremap(0x04000300,16); ++ // Look for the special 91c111 value in the bank select register ++ if((0xff00 & readw(network_controller_memory+0x0e)) == 0x3300) { ++ printk("Detected netCF-vx board: using older GPIO configuration\n"); ++ net_cf_vx_mode = 1; ++ } else { ++ printk("Not netCF-vx board: using newer GPIO configuration\n"); ++ net_cf_vx_mode = 0; ++ } ++ iounmap(network_controller_memory); ++} ++#endif ++ ++static int __init gumstix_pcmcia_init(void) ++{ ++ int ret; ++ ++#ifdef CONFIG_ARCH_GUMSTIX_VERDEX ++ gumstix_check_if_netCF_vx(); ++#endif ++ ++ gumstix_count_cards(); ++ ++ udelay(50); ++ if(net_cf_vx_mode) ++ GPCR(GPIO_GUMSTIX_CF_OLD_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_OLD_RESET); ++ else ++ GPCR(GPIO_GUMSTIX_CF_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_RESET); ++ ++ gumstix_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); ++ if (!gumstix_pcmcia_device) ++ return -ENOMEM; ++ ++ gumstix_pcmcia_device->dev.platform_data = &gumstix_pcmcia_ops; ++ ++ ret = platform_device_add(gumstix_pcmcia_device); ++ if (ret) ++ platform_device_put(gumstix_pcmcia_device); ++ ++ return ret; ++} ++ ++static void __exit gumstix_pcmcia_exit(void) ++{ ++ /* ++ * This call is supposed to free our gumstix_pcmcia_device. ++ * Unfortunately platform_device don't have a free method, and ++ * we can't assume it's free of any reference at this point so we ++ * can't free it either. ++ */ ++ platform_device_unregister(gumstix_pcmcia_device); ++} ++ ++fs_initcall(gumstix_pcmcia_init); ++module_exit(gumstix_pcmcia_exit); ++ ++MODULE_LICENSE("GPL"); |