
#
# Patch managed by http://www.holgerschurig.de/patcher.html
#

--- /dev/null
+++ linux-2.6.10-rc2/arch/arm/mach-pxa/corgi_ssp.c
@@ -0,0 +1,256 @@
+/*
+ *  SSP glue logic for Sharp Corgi
+ *
+ *  Copyright (c) 2004 Richard Purdie
+ *
+ *  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/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/ssp.h>
+#include <asm/arch/corgi.h>
+#include <asm/arch/pxa-regs.h>
+
+static spinlock_t corgi_ssp_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long flag;
+
+static struct ssp_dev corgi_ssp_dev;
+static struct ssp_state corgi_ssp_state;
+
+/*
+ *  ADS7846 Routines
+ */
+
+unsigned long corgi_ssp_ads7846_putget(ulong data)
+{
+	unsigned long ret;
+
+	spin_lock_irqsave(&corgi_ssp_lock, flag);
+
+	GPSR0 = GPIO_bit(GPIO19_DREQ1); /* TG */
+	GPSR0 = GPIO_bit(GPIO20_DREQ0); /* MAX1111 */
+	GPCR0 = GPIO_bit(GPIO24_SFRM); /* ADS7846 */
+
+	ssp_write_word(&corgi_ssp_dev,data);
+	ret = ssp_read_word(&corgi_ssp_dev);
+
+	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
+	return ret;
+}
+
+unsigned long corgi_ssp_ads7846_put(ulong data)
+{
+	spin_lock_irqsave(&corgi_ssp_lock, flag);
+
+	GPSR0 = GPIO_bit(GPIO19_DREQ1); /* TG */
+	GPSR0 = GPIO_bit(GPIO20_DREQ0); /* MAX1111 */
+	GPCR0 = GPIO_bit(GPIO24_SFRM); /* ADS7846 */
+
+	ssp_write_word(&corgi_ssp_dev,data);
+
+	return 0;
+}
+
+unsigned long corgi_ssp_ads7846_get(void)
+{
+	unsigned long ret;
+
+	ret = ssp_read_word(&corgi_ssp_dev);
+
+	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
+	return ret;
+}
+
+EXPORT_SYMBOL(corgi_ssp_ads7846_put);
+EXPORT_SYMBOL(corgi_ssp_ads7846_get);
+EXPORT_SYMBOL(corgi_ssp_ads7846_putget);
+
+/*
+ *  LCD/Backlight Routines
+ */
+
+#define TG_GPIO_GAFR0_MASK         0x000cc0c0
+
+static unsigned long ssp_put_dac_val(ulong data)
+{
+    int i;
+
+	spin_lock_irqsave(&corgi_ssp_lock, flag);
+
+	GPDR0 = (GPDR0 & ~GPIO_bit(GPIO26_SRXD))|
+		GPIO_bit(GPIO23_SCLK)|GPIO_bit(GPIO25_STXD);
+	GAFR0_U &= ~(TG_GPIO_GAFR0_MASK | 0x30300);
+	GPSR0 = GPIO_bit(20)|GPIO_bit(24);
+	GPCR0 = GPIO_bit(19)|GPIO_bit(23)|GPIO_bit(25)|GPIO_bit(26);
+	udelay(10);
+	for( i = 0; i < 8; i++){
+		if(data&0x80)
+			GPSR0 = GPIO_bit(25); /* SDO=H */
+		else
+			GPCR0 = GPIO_bit(25); /* SDO=L */
+		udelay(10);
+		GPSR0 = GPIO_bit(23); /* SCK=H */
+		udelay(10);
+		GPCR0 = GPIO_bit(23); /* SCK=L */
+		udelay(10);
+		data <<= 1;
+	}
+	GPCR0 = GPIO_bit(25); /* SDO=L */
+	GPSR0 = GPIO_bit(19); /* CSB=H */
+	GAFR0_U = (GAFR0_U & ~TG_GPIO_GAFR0_MASK)|0x88000;
+	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
+	return 0;
+}
+
+void corgi_ssp_lcdtg_send (u8 adrs, u8 data)
+{
+	ssp_put_dac_val (((adrs & 0x07) << 5) | (data & 0x1f));
+}
+
+void corgi_ssp_blduty_set (int duty) 
+{
+	ssp_put_dac_val(0x40 | ((duty) & 0x1f));
+}
+
+EXPORT_SYMBOL(corgi_ssp_lcdtg_send);
+EXPORT_SYMBOL(corgi_ssp_blduty_set);
+
+/*
+ *  Max1111 Routines
+ */
+
+int corgi_ssp_max1111_get(ulong data)
+{
+    volatile unsigned int dummy;
+    int voltage,voltage1,voltage2;
+
+    spin_lock_irqsave(&corgi_ssp_lock, flag);
+
+    SSCR0 = 0x387;
+    GPSR0 = GPIO_bit(GPIO19_DREQ1); /* TG */
+    GPCR0 = GPIO_bit(GPIO20_DREQ0); /* MAX1111 */
+    GPSR0 = GPIO_bit(GPIO24_SFRM); /* ADS7846 */
+
+    udelay(1);
+
+	/* TB1/RB1 */
+    SSDR = data;
+    while ((SSSR & SSSR_TNF) != SSSR_TNF);
+    udelay(1);
+    while ((SSSR & SSSR_RNE) != SSSR_RNE);
+    dummy = SSDR;
+
+	/* TB12/RB2 */
+    SSDR = 0;
+    while ((SSSR & SSSR_TNF) != SSSR_TNF);
+    udelay(1);
+    while ((SSSR & SSSR_RNE) != SSSR_RNE);
+    voltage1 = SSDR;
+
+	/* TB13/RB3*/
+    SSDR = 0;
+    while ((SSSR & SSSR_TNF) != SSSR_TNF);
+    udelay(1);
+    while ((SSSR & SSSR_RNE) != SSSR_RNE);
+    voltage2 = SSDR;
+
+    GPSR0 = GPIO_bit(GPIO19_DREQ1); /* TG */
+    GPSR0 = GPIO_bit(GPIO20_DREQ0); /* MAX1111 */
+    GPSR0 = GPIO_bit(GPIO24_SFRM); /* ADS7846 */
+    SSCR0 = 0xab;
+
+    if (voltage1 & 0xc0 || voltage2 & 0x3f){
+	voltage = -1;
+    }else{
+  	voltage = ((voltage1 << 2) & 0xfc) | ((voltage2 >> 6) & 0x03);
+    }
+
+    spin_unlock_irqrestore(&corgi_ssp_lock, flag);
+    return voltage;
+}
+
+EXPORT_SYMBOL(corgi_ssp_max1111_get);
+
+/*
+ *  Support Routines
+ */
+
+int __init corgi_ssp_probe(struct device *dev)
+{
+	int ret;
+
+	/* CS control disable all */
+	GPDR0 |= GPIO_bit(GPIO19_DREQ1); /* output */
+	GPSR0 = GPIO_bit(GPIO19_DREQ1); /* High */
+	GPDR0 |= GPIO_bit(GPIO20_DREQ0); /* output */
+	GPSR0 = GPIO_bit(GPIO20_DREQ0); /* High */
+	GPDR0 |= GPIO_bit(GPIO24_SFRM); /* output */
+	GPSR0 = GPIO_bit(GPIO24_SFRM); /* High */
+
+	ret=ssp_init(&corgi_ssp_dev,1,(SSCR0_National | (SSCR0_DSS & 0x0b )),0,0,SSCR0_SerClkDiv(2));
+	
+	if (!ret) ssp_enable(&corgi_ssp_dev);
+	else printk("Unable to register SSP handler!\n");
+	return ret;
+}
+
+static int corgi_ssp_remove(struct device *dev)
+{
+	ssp_exit(&corgi_ssp_dev);
+	return 0;
+}
+
+static int corgi_ssp_suspend(struct device *dev, u32 state, u32 level)
+{
+	if (level == SUSPEND_POWER_DOWN) {
+		spin_lock_irqsave(&corgi_ssp_lock, flag);
+		ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
+	}
+	return 0;
+}
+
+static int corgi_ssp_resume(struct device *dev, u32 level)
+{
+	if (level == RESUME_POWER_ON) {
+		GPSR0 = GPIO_bit(GPIO19_DREQ1); /* High */
+		GPSR0 = GPIO_bit(GPIO20_DREQ0); /* High */
+		GPSR0 = GPIO_bit(GPIO24_SFRM);  /* High */
+		ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
+		ssp_enable(&corgi_ssp_dev);
+		spin_unlock_irqrestore(&corgi_ssp_lock, flag);
+	}
+	return 0;
+}
+
+static struct device_driver corgissp_driver = {
+	.name		= "corgi-ssp",
+	.bus		= &platform_bus_type,
+	.probe		= corgi_ssp_probe,
+	.remove		= corgi_ssp_remove,
+	.suspend	= corgi_ssp_suspend,
+	.resume		= corgi_ssp_resume,
+};
+
+int __init corgi_ssp_init(void)
+{
+	return driver_register(&corgissp_driver);
+}
+
+void __exit corgi_ssp_exit(void)
+{
+ 	driver_unregister(&corgissp_driver);
+}

