diff -Nur cleancvs/kernel26/drivers/soc/Kconfig garage/kernel26/drivers/soc/Kconfig --- cleancvs/kernel26/drivers/soc/Kconfig 2005-07-03 15:43:32.000000000 +0200 +++ garage/kernel26/drivers/soc/Kconfig 2006-07-19 19:14:02.000000000 +0200 @@ -67,5 +67,8 @@ tristate "Support for TI TSC2101 Touchscreen and Audio Codec" help Support for TI TSC2101 Touchscreen and Audio Codec - +config SOC_TSC2200 + tristate "Support for Texas Instruments TSC2200" + help + Texas Instruments TSC2200 driver. endmenu diff -Nur cleancvs/kernel26/drivers/soc/Makefile garage/kernel26/drivers/soc/Makefile --- cleancvs/kernel26/drivers/soc/Makefile 2005-06-28 21:57:21.000000000 +0200 +++ garage/kernel26/drivers/soc/Makefile 2006-07-19 19:07:51.000000000 +0200 @@ -11,3 +11,4 @@ obj-$(CONFIG_HTC_ASIC3) += asic3_base.o obj-$(CONFIG_SOC_TSC2101) += tsc2101.o +obj-$(CONFIG_SOC_TSC2200) += tsc2200.o diff -Nur cleancvs/kernel26/drivers/soc/tsc2200.c garage/kernel26/drivers/soc/tsc2200.c --- cleancvs/kernel26/drivers/soc/tsc2200.c 1970-01-01 01:00:00.000000000 +0100 +++ garage/kernel26/drivers/soc/tsc2200.c 2006-07-19 19:46:43.000000000 +0200 @@ -0,0 +1,290 @@ +#include +#include +#include +#include +#include +#include +#include + +struct ssp_dev tsc2200_nssp_dev; +static spinlock_t nssp_lock; +DECLARE_MUTEX( tsc2200_sem ); +EXPORT_SYMBOL( tsc2200_sem ); + +static int nssp_bus_match(struct device *dev, struct device_driver *drv) +{ + printk("%s: %s -> %s\n", __FUNCTION__, dev->bus_id, drv->name); + if ( strstr( dev->bus_id, drv->name ) ) + return 1; + return 0; +} + +static void nssp_bus_release(struct device *dev) +{ + +} + +static int nssp_bus_suspend(struct device * dev, pm_message_t state) +{ + struct device_driver * drv = dev->driver; + +// if (drv && drv->suspend) +// return drv->suspend(dev, state, SUSPEND_POWER_DOWN); + return 0; +} + + +static int nssp_bus_resume(struct device * dev) +{ + struct device_driver * drv = dev->driver; + +// if (drv && drv->resume) +// drv->resume(dev, RESUME_POWER_ON); + return 0; +} + +void tsc2200_write(unsigned short reg, unsigned short val) +{ + unsigned long flags; + spin_lock_irqsave( &nssp_lock, flags ); + + ssp_write_word(&tsc2200_nssp_dev, reg); + ssp_write_word(&tsc2200_nssp_dev, val); + ssp_read_word(&tsc2200_nssp_dev); // dummy read for reg + ssp_read_word(&tsc2200_nssp_dev); // dummy read for val + + spin_unlock_irqrestore( &nssp_lock, flags ); +} +EXPORT_SYMBOL( tsc2200_write ); + +unsigned short tsc2200_read(unsigned short reg) +{ + unsigned short result; // initial value is ignored + unsigned long flags; + + reg |= TSC2200_REG_READ; + spin_lock_irqsave( &nssp_lock, flags ); + + ssp_write_word(&tsc2200_nssp_dev, reg); + ssp_write_word(&tsc2200_nssp_dev, 0); + ssp_read_word(&tsc2200_nssp_dev); // dummy read for reg + result = ssp_read_word(&tsc2200_nssp_dev); + + spin_unlock_irqrestore( &nssp_lock, flags ); + return result; +} +EXPORT_SYMBOL( tsc2200_read ); + +void tsc2200_reset(void) +{ + down_interruptible(&tsc2200_sem); + + tsc2200_write(TSC2200_CTRLREG_RESET, 0xBBFF); + + printk("%s: %X.\n", __FUNCTION__, tsc2200_read(TSC2200_CTRLREG_ADC)); + msleep(100); + printk("%s: %X.\n", __FUNCTION__, tsc2200_read(TSC2200_CTRLREG_ADC)); + + tsc2200_write(TSC2200_CTRLREG_ADC, + TSC2200_CTRLREG_ADC_PSM_TSC2200 | + TSC2200_CTRLREG_ADC_STS | + TSC2200_CTRLREG_ADC_AD0 | + TSC2200_CTRLREG_ADC_RES (TSC2200_CTRLREG_ADC_RES_12BITP) | + TSC2200_CTRLREG_ADC_AVG (TSC2200_CTRLREG_ADC_16AVG) | + TSC2200_CTRLREG_ADC_CL (TSC2200_CTRLREG_ADC_CL_2MHZ_12BIT) | + TSC2200_CTRLREG_ADC_PV (TSC2200_CTRLREG_ADC_PV_500uS) ); + tsc2200_write(TSC2200_CTRLREG_REF, 0x1F); + tsc2200_write(TSC2200_CTRLREG_CONFIG, 0xA); + tsc2200_write(TSC2200_CTRLREG_ADC, + TSC2200_CTRLREG_ADC_AD0 | + TSC2200_CTRLREG_ADC_RES (TSC2200_CTRLREG_ADC_RES_12BIT) | + TSC2200_CTRLREG_ADC_AVG (TSC2200_CTRLREG_ADC_16AVG) | + TSC2200_CTRLREG_ADC_CL (TSC2200_CTRLREG_ADC_CL_1MHZ_12BIT) | + TSC2200_CTRLREG_ADC_PV (TSC2200_CTRLREG_ADC_PV_100mS) ); + + up(&tsc2200_sem); +} +EXPORT_SYMBOL( tsc2200_reset ); + +int tsc2200_dav(void) +{ + return ( tsc2200_read(TSC2200_CTRLREG_CONFIG) & TSC2200_CTRLREG_CONFIG_DAV ) ? 0 : 1; +} +EXPORT_SYMBOL( tsc2200_dav ); + +static int tsc2200_probe(void)//struct device *dev ) +{ + if ( !machine_is_himalaya() && !machine_is_blueangel()) { + printk("%s: unknown iPAQ model %s\n", __FUNCTION__, /* h3600_generic_name() */ "Unknown" ); + return -ENODEV; + } + + printk("%s: initializing NSSP.\n", __FUNCTION__); + + spin_lock_init(&nssp_lock); + + pxa_gpio_mode(GPIO81_NSSP_CLK_OUT); + pxa_gpio_mode(GPIO82_NSSP_FRM_OUT); + pxa_gpio_mode(GPIO83_NSSP_TX); + pxa_gpio_mode(GPIO84_NSSP_RX); + GPSR(GPIO82_NSFRM) = GPIO_bit(GPIO82_NSFRM); + + ssp_init(&tsc2200_nssp_dev, 2, 0 ); + ssp_config(&tsc2200_nssp_dev, + SSCR0_Motorola | SSCR0_DataSize(0x10), + SSCR1_TTE | SSCR1_EBCEI | SSCR1_SPH | + SSCR1_TxTresh(1) | SSCR1_RxTresh(1), + 0, + SSCR0_SerClkDiv(0x14) + ); + ssp_enable(&tsc2200_nssp_dev); + + printk("%s: initializing the tsc2200.\n", __FUNCTION__); + + udelay(300); + tsc2200_reset(); + udelay(300); + + printk("%s: SPI: cr0 %08x cr1 %08x sr: %08x it: %08x to: %08x ps: %08x\n", + __FUNCTION__, + SSCR0_P2, SSCR1_P2, SSSR_P2, SSITR_P2, SSTO_P2, SSPSP_P2); + + return 0; +} +EXPORT_SYMBOL( tsc2200_probe ); + +static int tsc2200_remove( struct device *dev ) +{ + printk("%s: closing tsc2200.\n", __FUNCTION__); + + // nothing to do here + + printk("%s: closing NSSP.\n", __FUNCTION__); + + ssp_disable(&tsc2200_nssp_dev); + ssp_exit(&tsc2200_nssp_dev); + + pxa_gpio_mode(GPIO81_NSCLK); + pxa_gpio_mode(GPIO82_NSFRM); + pxa_gpio_mode(GPIO83_NSTXD); + pxa_gpio_mode(GPIO84_NSRXD); + GPCR(GPIO82_NSFRM) = GPIO_bit(GPIO82_NSFRM | + GPIO82_NSFRM | + GPIO83_NSTXD | + GPIO84_NSRXD); + + return 0; +} + +static int tsc2200_suspend (struct device *dev, u32 state, u32 level) +{ +/* if (level == SUSPEND_POWER_DOWN) { + printk("%s: SUSPEND_POWER_DOWN\n", __FUNCTION__); + ssp_disable(&tsc2200_nssp_dev); + } +*/ return 0; +} + +static int tsc2200_resume (struct device *dev, u32 level) +{ +/* if (level == RESUME_POWER_ON) { + printk("%s: RESUME_POWER_ON\n", __FUNCTION__); + ssp_config(&tsc2200_nssp_dev, + SSCR0_Motorola | SSCR0_DataSize(0x10), + SSCR1_TTE | SSCR1_EBCEI | SSCR1_SPH | + SSCR1_TxTresh(1) | SSCR1_RxTresh(1), + 0, + SSCR0_SerClkDiv(0x14) + ); + ssp_enable(&tsc2200_nssp_dev); + tsc2200_reset(); + } +*/ return 0; +} + +struct device nssp_bus = { + .bus_id = "nssp_bus", + .release = nssp_bus_release, +}; +EXPORT_SYMBOL( nssp_bus ); + +struct device_attribute nssp_dev_attrs[] = { +/* __ATTR_RO(resource), + __ATTR_RO(vendor), + __ATTR_RO(device), + __ATTR_RO(subsystem_vendor), + __ATTR_RO(subsystem_device), + __ATTR_RO(class), + __ATTR_RO(irq), */ + __ATTR_NULL, +}; + +struct bus_type nssp_bus_type = { + .name = "nssp", + .match = nssp_bus_match, +#ifdef CONFIG_PM + .suspend = nssp_bus_suspend, + .resume = nssp_bus_resume, +#endif + .dev_attrs = nssp_dev_attrs, +}; +EXPORT_SYMBOL( nssp_bus_type ); + +struct device_driver tsc2200_device_driver = { + .name = "tsc2200", + .bus = &nssp_bus_type, +// .probe = tsc2200_probe, + .remove = tsc2200_remove, +//#ifdef CONFIG_PM +// .suspend = tsc2200_suspend, +// .resume = tsc2200_resume, +//#if 0 +// .shutdown = tsc2200_shutdown, +//#endif +//#endif +}; +EXPORT_SYMBOL( tsc2200_device_driver ); + +static int __init tsc2200_init(void) +{ + printk("Register NSSP bus ... "); + + if ( device_register(&nssp_bus) ) + return 1; + if ( bus_register(&nssp_bus_type) ) + return 1; + + printk(" done.\n"); + + printk("%s: %X/%X.\n", __FUNCTION__, SSCR0_P2, SSCR0_SSE); + + printk("Register TSC2200 driver ... "); + + if ( driver_register (&tsc2200_device_driver) ) + return 1; + + printk(" done.\n"); + + printk("%s: %X/%X.\n", __FUNCTION__, SSCR0_P2, SSCR0_SSE); + tsc2200_probe(); + return 0; +} + +static void __exit tsc2200_exit (void) +{ + printk("Unregister TSC2200 driver.\n"); + + driver_unregister (&tsc2200_device_driver); + + printk("Unregister NSSP bus.\n"); + + bus_unregister(&nssp_bus_type); + device_unregister(&nssp_bus); +} + +module_init(tsc2200_init) +module_exit(tsc2200_exit) + +MODULE_AUTHOR("Matthias Burghardt"); +MODULE_DESCRIPTION("TSC2200 driver for Himalaya"); +MODULE_LICENSE("GPL"); /* I hope */