diff options
Diffstat (limited to 'packages/linux/linux-2.6.21')
-rw-r--r-- | packages/linux/linux-2.6.21/gumstix-pxa270-mmc.patch | 33 | ||||
-rw-r--r-- | packages/linux/linux-2.6.21/gumstix-verdex/defconfig | 12 | ||||
-rw-r--r-- | packages/linux/linux-2.6.21/mmc-card-detect.patch | 6 | ||||
-rw-r--r-- | packages/linux/linux-2.6.21/pxafb-18bpp-mode.patch | 17 | ||||
-rw-r--r-- | packages/linux/linux-2.6.21/pxafb-definition.patch | 42 | ||||
-rw-r--r-- | packages/linux/linux-2.6.21/smc911x-fixup.patch | 392 | ||||
-rw-r--r-- | packages/linux/linux-2.6.21/tsc2003-config.diff | 31 | ||||
-rw-r--r-- | packages/linux/linux-2.6.21/tsc2003.c | 557 |
8 files changed, 1059 insertions, 31 deletions
diff --git a/packages/linux/linux-2.6.21/gumstix-pxa270-mmc.patch b/packages/linux/linux-2.6.21/gumstix-pxa270-mmc.patch new file mode 100644 index 0000000000..59d97809d1 --- /dev/null +++ b/packages/linux/linux-2.6.21/gumstix-pxa270-mmc.patch @@ -0,0 +1,33 @@ +Index: linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c +=================================================================== +--- linux-2.6.21gum.orig/arch/arm/mach-pxa/gumstix.c ++++ linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c +@@ -33,8 +33,9 @@ + + static struct pxamci_platform_data gumstix_mci_platform_data; + +-static int gumstix_mci_init(struct device *dev, irqreturn_t (*gumstix_detect_int)(int, void *, struct pt_regs *), void *data) ++static int gumstix_mci_init(struct device *dev, irq_handler_t gumstix_detect_int, void *data) + { ++#ifndef CONFIG_ARCH_GUMSTIX_VERDEX + int err; + + pxa_gpio_mode(GPIO6_MMCCLK_MD); +@@ -55,6 +56,17 @@ static int gumstix_mci_init(struct devic + } + + err = set_irq_type(GUMSTIX_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE); ++#else ++ // Setup GPIOs for MMC on the 120-pin connector ++ // There is no card detect on a uSD connector so no interrupt to register ++ // There is no WP detect GPIO line either ++ pxa_gpio_mode(GPIO92_MMCDAT0_MD); ++ pxa_gpio_mode(GPIO112_MMCCMD_MD); ++ pxa_gpio_mode(GPIO110_MMCDAT2_MD); ++ pxa_gpio_mode(GPIO111_MMCDAT3_MD); ++ pxa_gpio_mode(GPIO109_MMCDAT1_MD); ++ pxa_gpio_mode(GPIO32_MMCCLK_MD); ++#endif + + return 0; + } diff --git a/packages/linux/linux-2.6.21/gumstix-verdex/defconfig b/packages/linux/linux-2.6.21/gumstix-verdex/defconfig index 9107cd0d7c..3057d62d5e 100644 --- a/packages/linux/linux-2.6.21/gumstix-verdex/defconfig +++ b/packages/linux/linux-2.6.21/gumstix-verdex/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.21 -# Thu Sep 13 14:49:02 2007 +# Mon Oct 8 11:22:41 2007 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -219,7 +219,7 @@ CONFIG_ALIGNMENT_HANDLING=0x2 # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=ttyS0,115200n8 root=1f01 rootfstype=jffs2" +CONFIG_CMDLINE="" # CONFIG_XIP_KERNEL is not set CONFIG_KEXEC=y @@ -828,7 +828,8 @@ CONFIG_MII=m CONFIG_SMC91X=m CONFIG_SMC91X_GUMSTIX=m # CONFIG_DM9000 is not set -# CONFIG_SMC911X is not set +CONFIG_SMC911X=m +CONFIG_SMC911X_GUMSTIX=m # # Ethernet (1000 Mbit) @@ -1057,6 +1058,8 @@ CONFIG_I2C_PXA_SLAVE=y # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_MAX6875 is not set +CONFIG_SENSORS_TSC2003=m +CONFIG_SENSORS_TSC2003_SYSFS=m # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -1137,6 +1140,9 @@ CONFIG_FB_PXA=y # CONFIG_FB_PXA_SHARP_LQ043_PSP is not set CONFIG_FB_PXA_SAMSUNG_LTE430WQ_F0C=y # CONFIG_FB_PXA_NONEOFTHEABOVE is not set +# CONFIG_FB_PXA_LCD_QVGA is not set +CONFIG_FB_PXA_LCD_VGA=y +CONFIG_FB_PXA_OVERLAY=y CONFIG_FB_PXA_PARAMETERS=y # CONFIG_FB_MBX is not set # CONFIG_FB_VIRTUAL is not set diff --git a/packages/linux/linux-2.6.21/mmc-card-detect.patch b/packages/linux/linux-2.6.21/mmc-card-detect.patch index 9a853b4df8..26dd970e3b 100644 --- a/packages/linux/linux-2.6.21/mmc-card-detect.patch +++ b/packages/linux/linux-2.6.21/mmc-card-detect.patch @@ -2,7 +2,7 @@ Index: linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c =================================================================== --- linux-2.6.21gum.orig/arch/arm/mach-pxa/gumstix.c +++ linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c -@@ -29,19 +29,51 @@ +@@ -29,19 +29,55 @@ #include "generic.h" @@ -38,9 +38,13 @@ Index: linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c +static int gumstix_mci_get_ro(struct device *dev) +{ ++#ifdef CONFIG_ARCH_GUMSTIX_VERDEX ++ return 0; // microSD is always writable on verdex ++#else + int ro; + ro = GPLR(GUMSTIX_GPIO_nSD_WP) & GPIO_bit(GUMSTIX_GPIO_nSD_WP); + return ro; ++#endif +} + +static void gumstix_mci_exit(struct device *dev, void *data) diff --git a/packages/linux/linux-2.6.21/pxafb-18bpp-mode.patch b/packages/linux/linux-2.6.21/pxafb-18bpp-mode.patch index 3643b402e5..c9849d22f4 100644 --- a/packages/linux/linux-2.6.21/pxafb-18bpp-mode.patch +++ b/packages/linux/linux-2.6.21/pxafb-18bpp-mode.patch @@ -154,7 +154,7 @@ Index: linux-2.6.21gum/drivers/video/pxafb.c case '-': namelen = i; if (!bpp_specified && !yres_specified) { -@@ -1227,6 +1268,18 @@ static int __init pxafb_parse_options(st +@@ -1227,12 +1268,29 @@ static int __init pxafb_parse_options(st } if (bpp_specified) switch (bpp) { @@ -173,6 +173,17 @@ Index: linux-2.6.21gum/drivers/video/pxafb.c case 1: case 2: case 4: + case 8: + case 16: + inf->modes[0].bpp = bpp; ++ if(nonstd_specified) { ++ dev_err(dev, "Depth %d requires nonstd to *not* be specified\n",bpp); ++ } else { ++ inf->modes[0].nonstd = 0; ++ } + dev_info(dev, "overriding bit depth: %d\n", bpp); + break; + default: Index: linux-2.6.21gum/include/asm-arm/arch-pxa/pxa-regs.h =================================================================== --- linux-2.6.21gum.orig/include/asm-arm/arch-pxa/pxa-regs.h @@ -217,7 +228,7 @@ Index: linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c =================================================================== --- linux-2.6.21gum.orig/arch/arm/mach-pxa/gumstix.c +++ linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c -@@ -100,7 +100,8 @@ static struct pxafb_mode_info gumstix_fb +@@ -116,7 +116,8 @@ static struct pxafb_mode_info gumstix_fb .pixclock = 110000, .xres = 480, .yres = 272, @@ -227,7 +238,7 @@ Index: linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c .hsync_len = 41, .left_margin = 2, .right_margin = 2, -@@ -139,7 +140,8 @@ static struct pxafb_mode_info gumstix_fb +@@ -144,7 +145,8 @@ static struct pxafb_mode_info gumstix_fb .vsync_len = 10, // VLW from datasheet: 10 typ .upper_margin = 2, // VBP - VLW from datasheet: 12 - 10 = 2 .lower_margin = 4, // VFP from datasheet: 4 typ diff --git a/packages/linux/linux-2.6.21/pxafb-definition.patch b/packages/linux/linux-2.6.21/pxafb-definition.patch index 2a782c6143..56369fd788 100644 --- a/packages/linux/linux-2.6.21/pxafb-definition.patch +++ b/packages/linux/linux-2.6.21/pxafb-definition.patch @@ -10,10 +10,26 @@ Index: linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c #include <asm/arch/gumstix.h> #include "generic.h" -@@ -86,6 +87,95 @@ static struct platform_device gum_audio_ +@@ -86,6 +87,89 @@ static struct platform_device gum_audio_ .id = -1, }; ++ ++#if defined(CONFIG_FB_PXA_SHARP_LQ043_PSP) || defined(CONFIG_FB_PXA_SAMSUNG_LTE430WQ_F0C) ++static void gumstix_lcd_backlight(int on_or_off) ++{ ++ if(on_or_off) ++ { ++ pxa_gpio_mode(17 | GPIO_IN); ++ } else { ++ GPCR(17) = GPIO_bit(17); ++ pxa_gpio_mode(17 | GPIO_OUT); ++ GPCR(17) = GPIO_bit(17); ++ } ++} ++#endif ++ ++ +#ifdef CONFIG_FB_PXA_ALPS_CDOLLAR +static struct pxafb_mode_info gumstix_fb_mode = { + .pixclock = 300000, @@ -50,17 +66,6 @@ Index: linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c + .sync = 0, // Hsync and Vsync both active low +}; + -+static void gumstix_lcd_backlight(int on_or_off) -+{ -+ pxa_gpio_mode(17 | GPIO_OUT); -+ if(on_or_off) -+ { -+ GPSR(17) = GPIO_bit(17); -+ } else { -+ GPCR(17) = GPIO_bit(17); -+ } -+} -+ +static struct pxafb_mach_info gumstix_fb_info = { + .modes = &gumstix_fb_mode, + .num_modes = 1, @@ -83,17 +88,6 @@ Index: linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c + .sync = 0, // Hsync and Vsync both active low +}; + -+static void gumstix_lcd_backlight(int on_or_off) -+{ -+ pxa_gpio_mode(17 | GPIO_OUT); -+ if(on_or_off) -+ { -+ GPSR(17) = GPIO_bit(17); -+ } else { -+ GPCR(17) = GPIO_bit(17); -+ } -+} -+ +static struct pxafb_mach_info gumstix_fb_info = { + .modes = &gumstix_fb_mode, + .num_modes = 1, @@ -106,7 +100,7 @@ Index: linux-2.6.21gum/arch/arm/mach-pxa/gumstix.c static struct platform_device *devices[] __initdata = { &gum_audio_device, }; -@@ -94,6 +184,9 @@ static void __init gumstix_init(void) +@@ -94,6 +178,9 @@ static void __init gumstix_init(void) { pxa_set_mci_info(&gumstix_mci_platform_data); pxa_set_udc_info(&gumstix_udc_info); diff --git a/packages/linux/linux-2.6.21/smc911x-fixup.patch b/packages/linux/linux-2.6.21/smc911x-fixup.patch new file mode 100644 index 0000000000..c0b7574d3a --- /dev/null +++ b/packages/linux/linux-2.6.21/smc911x-fixup.patch @@ -0,0 +1,392 @@ +Index: linux-2.6.21gum/drivers/net/smc911x.c +=================================================================== +--- linux-2.6.21gum.orig/drivers/net/smc911x.c ++++ linux-2.6.21gum/drivers/net/smc911x.c +@@ -76,6 +76,7 @@ static const char version[] = + #include <linux/etherdevice.h> + #include <linux/skbuff.h> + ++#include <linux/irq.h> + #include <asm/io.h> + #include <asm/irq.h> + +@@ -303,14 +304,14 @@ static void smc911x_reset(struct net_dev + SMC_SET_AFC_CFG(lp->afc_cfg); + + +- /* Set to LED outputs */ +- SMC_SET_GPIO_CFG(0x70070000); ++ /* Set to LED outputs and configure EEPROM pins as GP outputs */ ++ SMC_SET_GPIO_CFG(GPIO_CFG_LED1_EN_ | GPIO_CFG_LED2_EN_ | 1 << 20); + + /* +- * Deassert IRQ for 1*10us for edge type interrupts ++ * Deassert IRQ for 22*10us for edge type interrupts + * and drive IRQ pin push-pull + */ +- SMC_SET_IRQ_CFG( (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ ); ++ SMC_SET_IRQ_CFG( (22 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ ); + + /* clear anything saved */ + if (lp->pending_tx_skb != NULL) { +@@ -413,7 +414,7 @@ static inline void smc911x_drop_pkt(stru + if (fifo_count <= 4) { + /* Manually dump the packet data */ + while (fifo_count--) +- SMC_GET_RX_FIFO(); ++ (void)SMC_GET_RX_FIFO(); + } else { + /* Fast forward through the bad packet */ + SMC_SET_RX_DP_CTRL(RX_DP_CTRL_FFWD_BUSY_); +@@ -499,7 +500,7 @@ static inline void smc911x_rcv(struct n + SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_)); + SMC_PULL_DATA(data, pkt_len+2+3); + +- DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name,); ++ DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name); + PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64); + dev->last_rx = jiffies; + skb->dev = dev; +@@ -900,6 +901,7 @@ static void smc911x_phy_powerdown(struct + unsigned long ioaddr = dev->base_addr; + unsigned int bmcr; + ++ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + /* Enter Link Disable state */ + SMC_GET_PHY_BMCR(phy, bmcr); + bmcr |= BMCR_PDOWN; +@@ -925,6 +927,7 @@ static void smc911x_phy_check_media(stru + + if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) { + /* duplex state has changed */ ++ DBG(SMC_DEBUG_MISC, "%s: duplex state has changed\n", dev->name); + SMC_GET_PHY_BMCR(phyaddr, bmcr); + SMC_GET_MAC_CR(cr); + if (lp->mii.full_duplex) { +@@ -960,6 +963,7 @@ static void smc911x_phy_configure(struct + int my_phy_caps; /* My PHY capabilities */ + int my_ad_caps; /* My Advertised capabilities */ + int status; ++ int bmcr; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__); +@@ -1033,9 +1037,12 @@ static void smc911x_phy_configure(struct + + DBG(SMC_DEBUG_MISC, "%s: phy caps=0x%04x\n", dev->name, my_phy_caps); + DBG(SMC_DEBUG_MISC, "%s: phy advertised caps=0x%04x\n", dev->name, my_ad_caps); ++ DBG(SMC_DEBUG_MISC, "%s: phy advertised readback caps=0x%04x\n", dev->name, status); + + /* Restart auto-negotiation process in order to advertise my caps */ +- SMC_SET_PHY_BMCR(phyaddr, BMCR_ANENABLE | BMCR_ANRESTART); ++ SMC_GET_PHY_BMCR(phyaddr, bmcr); ++ bmcr |= BMCR_ANENABLE | BMCR_ANRESTART; ++ SMC_SET_PHY_BMCR(phyaddr, bmcr); + + smc911x_phy_check_media(dev, 1); + +@@ -1888,6 +1895,39 @@ static int __init smc911x_findirq(unsign + return probe_irq_off(cookie); + } + ++static inline unsigned int is_gumstix_oui(u8 *addr) ++{ ++ return (addr[0] == 0x00 && addr[1] == 0x15 && addr[2] == 0xC9); ++} ++ ++/** ++ * gen_serial_ether_addr - Generate software assigned Ethernet address ++ * based on the system_serial number ++ * @addr: Pointer to a six-byte array containing the Ethernet address ++ * ++ * Generate an Ethernet address (MAC) that is not multicast ++ * and has the local assigned bit set, keyed on the system_serial ++ */ ++static inline void gen_serial_ether_addr(u8 *addr) ++{ ++ static u8 ether_serial_digit = 0; ++ addr [0] = system_serial_high >> 8; ++ addr [1] = system_serial_high; ++ addr [2] = system_serial_low >> 24; ++ addr [3] = system_serial_low >> 16; ++ addr [4] = system_serial_low >> 8; ++ addr [5] = (system_serial_low & 0xc0) | /* top bits are from system serial */ ++ (1 << 4) | /* 2 bits identify interface type 1=ether, 2=usb, 3&4 undef */ ++ ((ether_serial_digit++) & 0x0f); /* 15 possible interfaces of each type */ ++ ++ if(!is_gumstix_oui(addr)) ++ { ++ addr [0] &= 0xfe; /* clear multicast bit */ ++ addr [0] |= 0x02; /* set local assignment bit (IEEE802) */ ++ } ++} ++ ++ + /* + * Function: smc911x_probe(unsigned long ioaddr) + * +@@ -2116,15 +2156,13 @@ static int __init smc911x_probe(struct n + #endif + printk("\n"); + if (!is_valid_ether_addr(dev->dev_addr)) { +- printk("%s: Invalid ethernet MAC address. Please " +- "set using ifconfig\n", dev->name); +- } else { +- /* Print the Ethernet address */ +- printk("%s: Ethernet addr: ", dev->name); +- for (i = 0; i < 5; i++) +- printk("%2.2x:", dev->dev_addr[i]); +- printk("%2.2x\n", dev->dev_addr[5]); ++ gen_serial_ether_addr(dev->dev_addr); + } ++ /* Print the Ethernet address */ ++ printk("%s: Ethernet addr: ", dev->name); ++ for (i = 0; i < 5; i++) ++ printk("%2.2x:", dev->dev_addr[i]); ++ printk("%2.2x\n", dev->dev_addr[5]); + + if (lp->phy_type == 0) { + PRINTK("%s: No PHY found\n", dev->name); +@@ -2300,8 +2338,15 @@ static struct platform_driver smc911x_dr + }, + }; + ++#ifdef CONFIG_ARCH_GUMSTIX ++extern void gumstix_smc911x_load(void); ++#endif ++ + static int __init smc911x_init(void) + { ++#ifdef CONFIG_ARCH_GUMSTIX ++ gumstix_smc911x_load(); ++#endif + return platform_driver_register(&smc911x_driver); + } + +Index: linux-2.6.21gum/drivers/net/gumstix-smc911x.c +=================================================================== +--- /dev/null ++++ linux-2.6.21gum/drivers/net/gumstix-smc911x.c +@@ -0,0 +1,148 @@ ++/* ++ * Gumstix SMC911x chip intialization driver ++ * ++ * Author: Craig Hughes ++ * Created: December 9, 2004 ++ * Copyright: (C) 2004 Craig Hughes ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ */ ++ ++#include <linux/module.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/platform_device.h> ++#include <linux/delay.h> ++ ++#include <asm/hardware.h> ++#include <asm/arch/pxa-regs.h> ++#include <asm/delay.h> ++ ++#include <asm/arch/gumstix.h> ++ ++#define SMC_DEBUG 9 ++#include <asm/io.h> ++#include "smc911x.h" ++ ++static struct resource gumstix_smc911x0_resources[] = { ++ [0] = { ++ .name = "smc911x-regs", ++ .start = PXA_CS1_PHYS, ++ .end = PXA_CS1_PHYS + 0x000fffff, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = GUMSTIX_ETH0_IRQ, ++ .end = GUMSTIX_ETH0_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct resource gumstix_smc911x1_resources[] = { ++ [0] = { ++ .name = "smc911x-regs", ++ .start = PXA_CS2_PHYS, ++ .end = PXA_CS2_PHYS + 0x000fffff, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = GUMSTIX_ETH1_IRQ, ++ .end = GUMSTIX_ETH1_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device gumstix_smc911x0_device = { ++ .name = "smc911x", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(gumstix_smc911x0_resources), ++ .resource = gumstix_smc911x0_resources, ++}; ++ ++static struct platform_device gumstix_smc911x1_device = { ++ .name = "smc911x", ++ .id = 1, ++ .num_resources = ARRAY_SIZE(gumstix_smc911x1_resources), ++ .resource = gumstix_smc911x1_resources, ++}; ++ ++static struct platform_device *smc911x_devices[] = { ++ &gumstix_smc911x0_device, ++ &gumstix_smc911x1_device, ++}; ++ ++/* First we're going to test if there's a 2nd SMC911x, and if not, then we'll free up those resources and the GPIO lines ++ * that it would otherwise use. We have no choice but to probe by doing: ++ * Set nCS2 to CS2 mode ++ * Set the reset line to GPIO out mode, and pull it high, then drop it low (to trigger reset) ++ * Read from the memory space to check for the sentinel sequence identifying a likely SMC911x device ++ */ ++int __init gumstix_smc911x_init(void) ++{ ++ unsigned int val, num_devices=ARRAY_SIZE(smc911x_devices); ++ void *ioaddr; ++ ++ /* Set up nPWE */ ++ pxa_gpio_mode(GPIO49_nPWE_MD); ++ ++ pxa_gpio_mode(GPIO78_nCS_2_MD); ++ // If either if statement fails, then we'll drop out and turn_off_eth1, ++ // if both succeed, then we'll skip that and just proceed with 2 cards ++ if(request_mem_region(gumstix_smc911x1_resources[1].start, SMC911X_IO_EXTENT, "smc911x probe")) ++ { ++ ioaddr = ioremap(gumstix_smc911x1_resources[1].start, SMC911X_IO_EXTENT); ++ val = SMC_GET_PN(); ++ iounmap(ioaddr); ++ release_mem_region(gumstix_smc911x1_resources[1].start, SMC911X_IO_EXTENT); ++ if (CHIP_9115 == val || ++ CHIP_9116 == val || ++ CHIP_9117 == val || ++ CHIP_9118 == val ) { ++ goto proceed; ++ } ++ } ++ ++turn_off_eth1: ++ // This is apparently not an SMC911x ++ // So, let's decrement the number of devices to request, and reset the GPIO lines to GPIO IN mode ++ num_devices--; ++ smc911x_devices[1] = NULL; ++ pxa_gpio_mode(78 | GPIO_IN); ++ ++proceed: ++ pxa_gpio_mode(GPIO15_nCS_1_MD); ++ ++ if(smc911x_devices[1]) pxa_gpio_mode(GPIO_GUMSTIX_ETH1_RST_MD); ++ pxa_gpio_mode(GPIO_GUMSTIX_ETH0_RST_MD); ++ ++ if(smc911x_devices[1]) GPCR(GPIO_GUMSTIX_ETH1_RST) = GPIO_bit(GPIO_GUMSTIX_ETH1_RST); ++ GPCR(GPIO_GUMSTIX_ETH0_RST) = GPIO_bit(GPIO_GUMSTIX_ETH0_RST); ++ msleep(500); // Hold RESET for at least 200µ ++ ++ if(smc911x_devices[1]) GPSR(GPIO_GUMSTIX_ETH1_RST) = GPIO_bit(GPIO_GUMSTIX_ETH1_RST); ++ GPSR(GPIO_GUMSTIX_ETH0_RST) = GPIO_bit(GPIO_GUMSTIX_ETH0_RST); ++ msleep(50); ++ ++ return platform_add_devices(smc911x_devices, num_devices); ++} ++ ++void __exit gumstix_smc911x_exit(void) ++{ ++ if(smc911x_devices[1] != NULL) platform_device_unregister(&gumstix_smc911x1_device); ++ platform_device_unregister(&gumstix_smc911x0_device); ++} ++ ++void gumstix_smc911x_load(void) {} ++EXPORT_SYMBOL(gumstix_smc911x_load); ++ ++module_init(gumstix_smc911x_init); ++module_exit(gumstix_smc911x_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Craig Hughes <craig@gumstix.com>"); ++MODULE_DESCRIPTION("Gumstix board SMC911x chip initialization driver"); ++MODULE_VERSION("1:0.1"); +Index: linux-2.6.21gum/drivers/net/Kconfig +=================================================================== +--- linux-2.6.21gum.orig/drivers/net/Kconfig ++++ linux-2.6.21gum/drivers/net/Kconfig +@@ -897,6 +897,13 @@ config SMC911X + called smc911x. If you want to compile it as a module, say M + here and read <file:Documentation/modules.txt> + ++config SMC911X_GUMSTIX ++ tristate ++ default m if SMC911X=m ++ default y if SMC911X=y ++ depends on SMC911X && ARCH_GUMSTIX ++ ++ + config NET_VENDOR_RACAL + bool "Racal-Interlan (Micom) NI cards" + depends on NET_ETHERNET && ISA +Index: linux-2.6.21gum/drivers/net/Makefile +=================================================================== +--- linux-2.6.21gum.orig/drivers/net/Makefile ++++ linux-2.6.21gum/drivers/net/Makefile +@@ -201,6 +201,7 @@ obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o + obj-$(CONFIG_MACB) += macb.o + + obj-$(CONFIG_SMC91X_GUMSTIX) += gumstix-smc91x.o ++obj-$(CONFIG_SMC911X_GUMSTIX) += gumstix-smc911x.o + obj-$(CONFIG_ARM) += arm/ + obj-$(CONFIG_DEV_APPLETALK) += appletalk/ + obj-$(CONFIG_TR) += tokenring/ +Index: linux-2.6.21gum/include/asm-arm/arch-pxa/gumstix.h +=================================================================== +--- linux-2.6.21gum.orig/include/asm-arm/arch-pxa/gumstix.h ++++ linux-2.6.21gum/include/asm-arm/arch-pxa/gumstix.h +@@ -52,7 +52,7 @@ + #define GPIO_GUMSTIX_ETH0_RST 80 + #define GPIO_GUMSTIX_ETH0 36 + #else +-#define GPIO_GUMSTIX_ETH0_RST 32 ++#define GPIO_GUMSTIX_ETH0_RST 107 + #define GPIO_GUMSTIX_ETH0 99 + #endif + #define GPIO_GUMSTIX_ETH1_RST 52 +Index: linux-2.6.21gum/drivers/net/smc911x.h +=================================================================== +--- linux-2.6.21gum.orig/drivers/net/smc911x.h ++++ linux-2.6.21gum/drivers/net/smc911x.h +@@ -33,7 +33,9 @@ + * Use the DMA feature on PXA chips + */ + #ifdef CONFIG_ARCH_PXA ++#ifndef CONFIG_SMC911X_GUMSTIX + #define SMC_USE_PXA_DMA 1 ++#endif + #define SMC_USE_16BIT 0 + #define SMC_USE_32BIT 1 + #endif +@@ -46,13 +48,13 @@ + #if SMC_USE_16BIT + #define SMC_inb(a, r) readb((a) + (r)) + #define SMC_inw(a, r) readw((a) + (r)) +-#define SMC_inl(a, r) ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw(a+2, r)<<16)) ++#define SMC_inl(a, r) ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw((a)+2, r)<<16)) + #define SMC_outb(v, a, r) writeb(v, (a) + (r)) + #define SMC_outw(v, a, r) writew(v, (a) + (r)) + #define SMC_outl(v, a, r) \ + do{ \ +- writel(v & 0xFFFF, (a) + (r)); \ +- writel(v >> 16, (a) + (r) + 2); \ ++ writel((v) & 0xFFFF, (a) + (r)); \ ++ writel((v) >> 16, (a) + (r) + 2); \ + } while (0) + #define SMC_insl(a, r, p, l) readsw((short*)((a) + (r)), p, l*2) + #define SMC_outsl(a, r, p, l) writesw((short*)((a) + (r)), p, l*2) diff --git a/packages/linux/linux-2.6.21/tsc2003-config.diff b/packages/linux/linux-2.6.21/tsc2003-config.diff new file mode 100644 index 0000000000..ccad5ed696 --- /dev/null +++ b/packages/linux/linux-2.6.21/tsc2003-config.diff @@ -0,0 +1,31 @@ +--- /tmp/Kconfig 2007-10-07 14:13:14.000000000 +0200 ++++ linux-2.6.21/drivers/i2c/chips/Kconfig 2007-10-07 14:13:56.902045000 +0200 +@@ -125,4 +125,18 @@ + This driver can also be built as a module. If so, the module + will be called max6875. + ++config SENSORS_TSC2003 ++ tristate "TI TSC2003" ++ depends on I2C && EXPERIMENTAL ++ default n ++ help ++ Driver for TI tsc2003 touchscreen and sensor chip/ ++ ++config SENSORS_TSC2003_SYSFS ++ tristate "TI TSC2003 sysfs interface ++ depends on SENSORS_TSC2003 ++ default n ++ help ++ Enabled the sysfs interface for tsc2003 ++ + endmenu +--- /tmp/Makefile 2007-10-07 14:14:14.000000000 +0200 ++++ linux-2.6.21/drivers/i2c/chips/Makefile 2007-10-07 14:14:20.072045000 +0200 +@@ -12,6 +12,7 @@ + obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o + obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o + obj-$(CONFIG_TPS65010) += tps65010.o ++obj-$(CONFIG_SENSORS_TSC2003) += tsc2003.o + + ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) + EXTRA_CFLAGS += -DDEBUG diff --git a/packages/linux/linux-2.6.21/tsc2003.c b/packages/linux/linux-2.6.21/tsc2003.c new file mode 100644 index 0000000000..8d7e5b3f78 --- /dev/null +++ b/packages/linux/linux-2.6.21/tsc2003.c @@ -0,0 +1,557 @@ +/* + * linux/drivers/i2c/chips/tsc2003.c + * + * Copyright (C) 2005 Bill Gatliff <bgat at billgatliff.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. + * + * Driver for TI's TSC2003 I2C Touch Screen Controller + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/string.h> +#include <linux/bcd.h> +#include <linux/list.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/input.h> +#include <linux/platform_device.h> +#include <asm/delay.h> +#include <linux/delay.h> + +#include <asm/arch/gpio.h> + +#define DRIVER_NAME "tsc2003" + +enum tsc2003_pd { + PD_POWERDOWN = 0, /* penirq */ + PD_IREFOFF_ADCON = 1, /* no penirq */ + PD_IREFON_ADCOFF = 2, /* penirq */ + PD_IREFON_ADCON = 3, /* no penirq */ + PD_PENIRQ_ARM = PD_IREFON_ADCOFF, + PD_PENIRQ_DISARM = PD_IREFON_ADCON, +}; + +enum tsc2003_m { + M_12BIT = 0, + M_8BIT = 1 +}; + +enum tsc2003_cmd { + MEAS_TEMP0 = 0, + MEAS_VBAT1 = 1, + MEAS_IN1 = 2, + MEAS_TEMP1 = 4, + MEAS_VBAT2 = 5, + MEAS_IN2 = 6, + ACTIVATE_NX_DRIVERS = 8, + ACTIVATE_NY_DRIVERS = 9, + ACTIVATE_YNX_DRIVERS = 10, + MEAS_XPOS = 12, + MEAS_YPOS = 13, + MEAS_Z1POS = 14, + MEAS_Z2POS = 15 +}; + +#define TSC2003_CMD(cn,pdn,m) (((cn) << 4) | ((pdn) << 2) | ((m) << 1)) + +#define ADC_MAX ((1 << 12) - 1) + +struct tsc2003_data { + struct i2c_client *client; + struct input_dev *idev; + struct timer_list penirq_timer; + struct semaphore sem; + struct task_struct *tstask; + struct completion tstask_completion; + enum tsc2003_pd pd; + enum tsc2003_m m; + int vbat1; + int vbat2; + int temp0; + int temp1; + int in1; + int in2; +}; + +static int tsc2003_i2c_detect (struct i2c_adapter *adapter, int address, + int kind); + +static inline int tsc2003_command (struct tsc2003_data *data, + enum tsc2003_cmd cmd, + enum tsc2003_pd pd) +{ + char c; + int ret; + down(&data->sem); + c = TSC2003_CMD(cmd, pd, data->m); + ret = i2c_master_send(data->client, &c, 1); + up(&data->sem); + return ret; +} + +static int tsc2003_read (struct tsc2003_data *data, + enum tsc2003_cmd cmd, + enum tsc2003_pd pd, + int *val) +{ + char c; + char d[2]; + int ret; + + c = TSC2003_CMD(cmd, pd, data->m); + ret = i2c_master_send(data->client, &c, 1); + + udelay(20); + ret = i2c_master_recv(data->client, d, data->m == M_12BIT ? 2 : 1); + + if (val) + { + *val = d[0]; + *val <<= 4; + if (data->m == M_12BIT) + *val += (d[1] >> 4); + } + +#if defined(CONFIG_I2C_DEBUG_CHIP) + printk(KERN_ERR "%s: val[%x] = %d\n", + __FUNCTION__, cmd, (((int)d[0]) << 8) + d[1]); +#endif + + return 0; + if (!ret) ret = -ENODEV; + return ret; +} + +static inline int tsc2003_read_temp0 (struct tsc2003_data *d, enum + tsc2003_pd pd, int *t) +{ + return tsc2003_read(d, MEAS_TEMP0, pd, t); +} + +static inline int tsc2003_read_temp1 (struct tsc2003_data *d, enum + tsc2003_pd pd, int *t) +{ + return tsc2003_read(d, MEAS_TEMP1, pd, t); +} + +static inline int tsc2003_read_xpos (struct tsc2003_data *d, enum + tsc2003_pd pd, int *x) +{ + return tsc2003_read(d, MEAS_XPOS, pd, x); +} + +static inline int tsc2003_read_ypos (struct tsc2003_data *d, enum + tsc2003_pd pd, int *y) +{ + return tsc2003_read(d, MEAS_YPOS, pd, y); +} + +static inline int tsc2003_read_pressure (struct tsc2003_data *d, enum + tsc2003_pd pd, int *p) +{ + return tsc2003_read(d, MEAS_Z1POS, pd, p); +} + +static inline int tsc2003_read_in1 (struct tsc2003_data *d, enum + tsc2003_pd pd, int *t) +{ + return tsc2003_read(d, MEAS_IN1, pd, t); +} + +static inline int tsc2003_read_in2 (struct tsc2003_data *d, enum + tsc2003_pd pd, int *t) +{ + return tsc2003_read(d, MEAS_IN2, pd, t); +} + +static inline int tsc2003_read_vbat1 (struct tsc2003_data *d, enum + tsc2003_pd pd, int *t) +{ + return tsc2003_read(d, MEAS_VBAT1, pd, t); +} + +static inline int tsc2003_read_vbat2 (struct tsc2003_data *d, enum + tsc2003_pd pd, int *t) +{ + return tsc2003_read(d, MEAS_VBAT2, pd, t); +} + +static inline int tsc2003_powerdown (struct tsc2003_data *d) +{ + /* we don't have a distinct powerdown command, + so do a benign read with the PD bits cleared */ + return tsc2003_read(d, MEAS_IN1, PD_POWERDOWN, 0); +} + +void tsc2003_init_client (struct i2c_client *client) +{ + struct tsc2003_data *data = i2c_get_clientdata(client); + + data->pd = PD_PENIRQ_DISARM; + data->m = M_8BIT; + return; +} + +static int tsc2003ts_thread (void *v) +{ + struct tsc2003_data *d = v; + struct task_struct *tsk = current; + int pendown=0; + + d->tstask = tsk; + + daemonize(DRIVER_NAME "tsd"); + allow_signal(SIGKILL); + + complete(&d->tstask_completion); + + printk(KERN_INFO "%s: address 0x%x\n", + __FUNCTION__, d->client->addr); + + while (!signal_pending(tsk)) + { + unsigned int x, y, p; + + tsc2003_read_xpos(d, PD_PENIRQ_DISARM, &x); + tsc2003_read_ypos(d, PD_PENIRQ_DISARM, &y); + tsc2003_read_pressure(d, PD_PENIRQ_DISARM, &p); + + /* non-X-Y driver read to avoid glitch in penirq (errata?) */ + if (p > 100) { + pendown = 1; + input_report_abs(d->idev, ABS_X, x); + input_report_abs(d->idev, ABS_Y, y); + input_report_abs(d->idev, ABS_PRESSURE, p); + input_report_key(d->idev, BTN_TOUCH, 1); + input_sync(d->idev); + } else if (pendown == 1) { + pendown = 0; + input_report_key(d->idev, BTN_TOUCH, 0); + input_report_abs(d->idev, ABS_PRESSURE, 0); + input_sync(d->idev); + } + schedule_timeout_interruptible(msecs_to_jiffies(10)); + } + + d->tstask = NULL; + complete_and_exit(&d->tstask_completion, 0); +} + +static int tsc2003_idev_open (struct input_dev *idev) +{ + struct tsc2003_data *d = idev->private; + int ret = 0; + + if (down_interruptible(&d->sem)) + return -EINTR; + + if (d->tstask) + panic(DRIVER_NAME "tsd already running (!). abort."); + + init_completion(&d->tstask_completion); + + ret = kernel_thread(tsc2003ts_thread, d, CLONE_KERNEL); + if (ret >= 0) { + wait_for_completion(&d->tstask_completion); + ret = 0; + } + + up(&d->sem); + + return ret; +} + +static void tsc2003_idev_close (struct input_dev *idev) +{ + struct tsc2003_data *d = idev->private; + down_interruptible(&d->sem); + if (d->tstask) + { + send_sig(SIGKILL, d->tstask, 1); + wait_for_completion(&d->tstask_completion); + } + up(&d->sem); + return; +} + +#if defined(CONFIG_SYSFS) && defined(CONFIG_SENSORS_TSC2003_SYSFS) +static ssize_t show_addr (struct device *dev, char *buf) +{ + struct tsc2003_data *d = container_of(dev->driver, struct + tsc2003_data, driver); + return sprintf(buf, "%d\n", d->client.addr); +} +static DEVICE_ATTR(addr, S_IRUGO, show_addr, NULL); + +static ssize_t show_vbat1 (struct device *dev, char *buf) +{ + struct tsc2003_data *d = container_of(dev->driver, struct + tsc2003_data, driver); + return sprintf(buf, "%d\n", d->vbat1); +} +static DEVICE_ATTR(vbat1, S_IRUGO, show_vbat1, NULL); + +static ssize_t show_vbat2 (struct device *dev, char *buf) +{ + struct tsc2003_data *d = container_of(dev->driver, struct + tsc2003_data, driver); + return sprintf(buf, "%d\n", d->vbat2); +} +static DEVICE_ATTR(vbat2, S_IRUGO, show_vbat2, NULL); + +static ssize_t show_in1 (struct device *dev, char *buf) +{ + struct tsc2003_data *d = container_of(dev->driver, struct + tsc2003_data, driver); + return sprintf(buf, "%d\n", d->in1); +} +static DEVICE_ATTR(in1, S_IRUGO, show_in1, NULL); + +static ssize_t show_in2 (struct device *dev, char *buf) +{ + struct tsc2003_data *d = container_of(dev->driver, struct + tsc2003_data, driver); + return sprintf(buf, "%d\n", d->in2); +} +static DEVICE_ATTR(in2, S_IRUGO, show_in2, NULL); + +static ssize_t show_temp0 (struct device *dev, char *buf) +{ + struct tsc2003_data *d = container_of(dev->driver, struct + tsc2003_data, driver); + return sprintf(buf, "%d\n", d->temp0); +} +static DEVICE_ATTR(temp0, S_IRUGO, show_temp0, NULL); + +static ssize_t show_temp1 (struct device *dev, char *buf) +{ + struct tsc2003_data *d = container_of(dev->driver, struct + tsc2003_data, driver); + return sprintf(buf, "%d\n", d->temp1); +} +static DEVICE_ATTR(temp1, S_IRUGO, show_temp1, NULL); + +#warning "TODO: this daemon sometimes hangs the touchscreen daemon" +#warning "TODO: under periods of heavy touch screen activity." +#warning "TODO: Use with caution until the bug is squashed." +static int tsc2003s_thread (void *v) +{ + struct tsc2003_data *d = v; + + daemonize(DRIVER_NAME "sd"); + allow_signal(SIGKILL); + + printk(KERN_INFO "%s: address 0x%x\n", + __FUNCTION__, d->client.addr); + + while (!signal_pending(current)) + { + if (!down_interruptible(&d->sem)) + { + if (!timer_pending(&d->penirq_timer)) + { + tsc2003_read_vbat1(d, d->pd, &d->vbat1); + tsc2003_read_vbat2(d, d->pd, &d->vbat2); + tsc2003_read_in1(d, d->pd, &d->in1); + tsc2003_read_in2(d, d->pd, &d->in2); + tsc2003_read_temp0(d, d->pd, &d->temp0); + tsc2003_read_temp1(d, d->pd, &d->temp1); + } + up(&d->sem); + } + set_task_state(current, TASK_INTERRUPTIBLE); + schedule_timeout(5 * HZ); + } + do_exit(0); +} +#endif + +static int tsc2003_driver_register (struct tsc2003_data *data) +{ + int ret = 0; + + init_MUTEX(&data->sem); + + data->idev = input_allocate_device(); + if(!data->idev) + { + return -ENOMEM; + } + data->idev->private = data; + data->idev->name = DRIVER_NAME; + data->idev->evbit[0] = BIT(EV_ABS); + data->idev->open = tsc2003_idev_open; + data->idev->close = tsc2003_idev_close; + data->idev->absbit[LONG(ABS_X)] = BIT(ABS_X); + data->idev->absbit[LONG(ABS_Y)] = BIT(ABS_Y); + data->idev->absbit[LONG(ABS_PRESSURE)] = BIT(ABS_PRESSURE); + input_set_abs_params(data->idev, ABS_X, 0, ADC_MAX, 0, 0); + input_set_abs_params(data->idev, ABS_Y, 0, ADC_MAX, 0, 0); + + ret = input_register_device(data->idev); + if(ret) + { + input_free_device(data->idev); + return ret; + } + return ret; +} + +/* Magic definition of all other variables and things */ +static unsigned short normal_i2c[] = {0x48, 0x49, 0x4a, 0x48b, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + +static int tsc2003_i2c_attach_adapter(struct i2c_adapter *adapter) +{ + return i2c_probe(adapter, &addr_data, tsc2003_i2c_detect); +} + +static int tsc2003_i2c_detach_client(struct i2c_client *client) +{ + struct tsc2003_data *data=i2c_get_clientdata(client); + int err; + + input_unregister_device(data->idev); + + err = i2c_detach_client(client); + if (err) { + dev_err(&client->dev, "Client deregistration failed, " + "client not detached.\n"); + return err; + } + + return 0; +} + +static struct i2c_driver tsc2003_i2c_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRIVER_NAME, + }, + .attach_adapter = tsc2003_i2c_attach_adapter, + .detach_client = tsc2003_i2c_detach_client, + .command = NULL +}; + +static struct i2c_client client_template = { + .name = "TSC2003", + .driver = &tsc2003_i2c_driver, +}; + +static int tsc2003_i2c_detect (struct i2c_adapter *adap, int addr, + int kind) +{ + struct i2c_client *i2c; + int ret; + struct tsc2003_data *data; + + client_template.adapter = adap; + client_template.addr = addr; + + printk(KERN_INFO "tsc2003 i2c touch screen controller\n"); + printk(KERN_INFO "Bill Gatliff <bgat at billgatliff.com>\n"); + + i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); + if (i2c == NULL){ + return -ENOMEM; + } + + data = kcalloc(1, sizeof(*data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto err; + } + data->client = i2c; + i2c_set_clientdata(i2c, data); + + ret = i2c_attach_client(i2c); + + if (ret < 0) { + printk("failed to attach codec at addr %x\n", addr); + goto err; + } + + tsc2003_init_client(i2c); + + tsc2003_powerdown(data); + + ret = tsc2003_driver_register(data); + if(ret < 0) { + printk("driver_register failed\n"); + goto err; + } + + return ret; + +err: + kfree(i2c); + return ret; +} + +#define tsc2003_suspend NULL +#define tsc2003_resume NULL + +static int __devinit tsc2003_probe(struct platform_device *dev) +{ + int ret; + + ret=i2c_add_driver(&tsc2003_i2c_driver); + if(ret) + return ret; + +#if defined(CONFIG_SYSFS) && defined(CONFIG_SENSORS_TSC2003_SYSFS) + ret = kernel_thread(tsc2003s_thread, d, CLONE_KERNEL); + if (ret >= 0) + ret = 0; + + device_create_file(dev, &dev_attr_addr); + device_create_file(dev, &dev_attr_vbat1); + device_create_file(dev, &dev_attr_vbat2); + device_create_file(dev, &dev_attr_in1); + device_create_file(dev, &dev_attr_in2); + device_create_file(dev, &dev_attr_temp0); + device_create_file(dev, &dev_attr_temp1); +#endif + return 0; +} + +static int __devexit tsc2003_remove(struct platform_device *dev) +{ + i2c_del_driver(&tsc2003_i2c_driver); + return 0; +} + +static struct platform_driver tsc2003_driver = { + .probe = tsc2003_probe, + .remove = __devexit_p(tsc2003_remove), + .suspend = tsc2003_suspend, + .resume = tsc2003_resume, + .driver = { + .name = "tsc2003", + }, +}; + +static int __init tsc2003_init(void) +{ + return platform_driver_register(&tsc2003_driver); +} + +static void __exit tsc2003_exit(void) +{ + platform_driver_unregister(&tsc2003_driver); +} + +MODULE_AUTHOR("Bill Gatliff <bgat at billgatliff.com>"); +MODULE_DESCRIPTION("TSC2003 Touch Screen Controller driver"); +MODULE_LICENSE("GPL"); + +module_init(tsc2003_init); +module_exit(tsc2003_exit); |