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

--- /dev/null
+++ linux-2.6.10/arch/arm/mach-pxa/corgi_ssp.c
@@ -0,0 +1,247 @@
+/*
+ *  SSP control code for Sharp Corgi devices
+ *
+ *  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/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <asm/hardware.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 struct ssp_dev corgi_ssp_dev;
+static struct ssp_state corgi_ssp_state;
+
+/*
+ * There are three devices connected to the SSP interface:
+ *   1. A touchscreen controller (TI ADS7846 compatible) 
+ *   2. An LCD contoller (with some Backlight functionality)
+ *   3. A battery moinitoring IC (Maxim MAX1111)
+ * 
+ * Each device uses a different speed/mode of communication. 
+ *
+ * The touchscreen is very sensitive and the most frequently used
+ * so the port is left configured for this.
+ * 
+ * Devices are selected using Chip Selects on GPIOs.
+ */
+
+/*
+ *  ADS7846 Routines
+ */
+unsigned long corgi_ssp_ads7846_putget(ulong data)
+{
+	unsigned long ret,flag;
+
+	spin_lock_irqsave(&corgi_ssp_lock, flag);
+	GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+
+	ssp_write_word(&corgi_ssp_dev,data);
+	ret = ssp_read_word(&corgi_ssp_dev);
+
+	GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
+
+	return ret;
+}
+
+/* 
+ * NOTE: These functions should always be called in interrupt context 
+ * and use the _lock and _unlock functions. They are very time sensitive.
+ */
+void corgi_ssp_ads7846_lock(void)
+{
+	spin_lock(&corgi_ssp_lock);
+	GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+}
+
+void corgi_ssp_ads7846_unlock(void)
+{
+	GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+	spin_unlock(&corgi_ssp_lock);
+}
+
+void corgi_ssp_ads7846_put(ulong data)
+{
+	ssp_write_word(&corgi_ssp_dev,data);
+}
+
+unsigned long corgi_ssp_ads7846_get(void)
+{
+	return ssp_read_word(&corgi_ssp_dev);
+}
+
+EXPORT_SYMBOL(corgi_ssp_ads7846_putget);
+EXPORT_SYMBOL(corgi_ssp_ads7846_lock);
+EXPORT_SYMBOL(corgi_ssp_ads7846_unlock);
+EXPORT_SYMBOL(corgi_ssp_ads7846_put);
+EXPORT_SYMBOL(corgi_ssp_ads7846_get);
+
+
+/*
+ *  LCD/Backlight Routines
+ */
+unsigned long corgi_ssp_dac_put(ulong data)
+{
+	unsigned long flag;
+	
+	spin_lock_irqsave(&corgi_ssp_lock, flag);
+	GPCR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
+
+	ssp_disable(&corgi_ssp_dev);
+	ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), SSCR1_SPH, 0, SSCR0_SerClkDiv(76));
+	ssp_enable(&corgi_ssp_dev);
+
+	ssp_write_word(&corgi_ssp_dev,data);
+	/* Read null data back from device to prevent SSP overflow */
+	ssp_read_word(&corgi_ssp_dev);
+
+	ssp_disable(&corgi_ssp_dev);
+	ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+	ssp_enable(&corgi_ssp_dev);
+	GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
+	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
+
+	return 0;
+}
+
+void corgi_ssp_lcdtg_send(u8 adrs, u8 data)
+{
+	corgi_ssp_dac_put(((adrs & 0x07) << 5) | (data & 0x1f));
+}
+
+void corgi_ssp_blduty_set(int duty) 
+{
+	corgi_ssp_lcdtg_send(0x02,duty);
+}
+
+EXPORT_SYMBOL(corgi_ssp_lcdtg_send);
+EXPORT_SYMBOL(corgi_ssp_blduty_set);
+
+/*
+ *  Max1111 Routines
+ */
+int corgi_ssp_max1111_get(ulong data)
+{
+	unsigned long flag;
+	int voltage,voltage1,voltage2;
+
+	spin_lock_irqsave(&corgi_ssp_lock, flag);
+	GPCR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
+	ssp_disable(&corgi_ssp_dev);
+	ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(8));
+	ssp_enable(&corgi_ssp_dev);
+
+	udelay(1);
+
+	/* TB1/RB1 */
+	ssp_write_word(&corgi_ssp_dev,data);
+	ssp_read_word(&corgi_ssp_dev); /* null read */
+
+	/* TB12/RB2 */
+	ssp_write_word(&corgi_ssp_dev,0);
+	voltage1=ssp_read_word(&corgi_ssp_dev);
+
+	/* TB13/RB3*/
+	ssp_write_word(&corgi_ssp_dev,0);
+	voltage2=ssp_read_word(&corgi_ssp_dev);
+
+	ssp_disable(&corgi_ssp_dev);
+	ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+	ssp_enable(&corgi_ssp_dev);
+	GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
+	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
+
+	if (voltage1 & 0xc0 || voltage2 & 0x3f)	
+		voltage = -1;
+	else 
+		voltage = ((voltage1 << 2) & 0xfc) | ((voltage2 >> 6) & 0x03);
+
+	return voltage;
+}
+
+EXPORT_SYMBOL(corgi_ssp_max1111_get);
+
+/*
+ *  Support Routines
+ */
+int __init corgi_ssp_probe(struct device *dev)
+{
+	int ret;
+
+	/* Chip Select - Disable All */
+	GPDR0 |= GPIO_bit(CORGI_GPIO_LCDCON_CS); /* output */
+	GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);  /* High - Disable LCD Control/Timing Gen */
+	GPDR0 |= GPIO_bit(CORGI_GPIO_MAX1111_CS); /* output */
+	GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);  /* High - Disable MAX1111*/
+	GPDR0 |= GPIO_bit(CORGI_GPIO_ADS7846_CS);  /* output */
+	GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);   /* High - Disable ADS7846*/
+
+	ret=ssp_init(&corgi_ssp_dev,1);
+
+	if (ret) 
+		printk(KERN_ERR "Unable to register SSP handler!\n");
+	else {
+		ssp_disable(&corgi_ssp_dev);
+		ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+		ssp_enable(&corgi_ssp_dev);
+	}
+	
+	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) {
+		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(CORGI_GPIO_LCDCON_CS);  /* High - Disable LCD Control/Timing Gen */
+		GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
+		GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/		
+		ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
+		ssp_enable(&corgi_ssp_dev);
+	}
+	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);
+}
+
+arch_initcall(corgi_ssp_init);
--- linux-2.6.10/arch/arm/mach-pxa/Makefile~corgi_ssp-r6.patch
+++ linux-2.6.10/arch/arm/mach-pxa/Makefile
@@ -11,7 +11,7 @@
 obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
 obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
 obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
-obj-$(CONFIG_PXA_SHARPSL)	+= corgi.o
+obj-$(CONFIG_PXA_SHARPSL)	+= corgi.o corgi_ssp.o ssp.o
 
 # Support for blinky lights
 led-y := leds.o
--- linux-2.6.10/include/asm-arm/arch-pxa/corgi.h~corgi_ssp-r6.patch
+++ linux-2.6.10/include/asm-arm/arch-pxa/corgi.h
@@ -15,29 +15,31 @@
 
 
 /*
- * Corgi GPIO definitions
+ * Corgi (Non Standard) GPIO Definitions
  */
-#define CORGI_GPIO_KEY_INT			(0)	/* key interrupt */
+#define CORGI_GPIO_KEY_INT			(0)	/* Keyboard Interrupt */
 #define CORGI_GPIO_AC_IN			(1)
 #define CORGI_GPIO_WAKEUP			(3)
-#define CORGI_GPIO_AK_INT			(4)	// Remote Controller
-#define CORGI_GPIO_TP_INT			(5)	/* Touch Panel interrupt */
-#define CORGI_GPIO_nSD_CLK			(6)
+#define CORGI_GPIO_AK_INT			(4)	/* IR Controller Interrupt */
+#define CORGI_GPIO_TP_INT			(5)	/* Touch Panel Interrupt */
 #define CORGI_GPIO_nSD_WP			(7)
-#define CORGI_GPIO_nSD_DETECT		(9)
+#define CORGI_GPIO_nSD_DETECT		(9) /* MMC/SD Card Detect */
 #define CORGI_GPIO_nSD_INT			(10)
 #define CORGI_GPIO_MAIN_BAT_LOW		(11)
 #define CORGI_GPIO_BAT_COVER		(11)
 #define CORGI_GPIO_LED_ORANGE		(13)
-#define CORGI_GPIO_CF_CD			(14)
-#define CORGI_GPIO_CHRG_FULL		(16)
-#define CORGI_GPIO_CF_IRQ			(17)
+#define CORGI_GPIO_CF_CD			(14) /* Compact Flash Card Detect */
+#define CORGI_GPIO_CHRG_FULL		(16) 
+#define CORGI_GPIO_CF_IRQ			(17) /* Compact Flash Interrupt */
+#define CORGI_GPIO_LCDCON_CS		(19) /* LCD Control Chip Select */
+#define CORGI_GPIO_MAX1111_CS		(20) /* MAX111 Chip Select */
 #define CORGI_GPIO_ADC_TEMP_ON		(21)
 #define CORGI_GPIO_IR_ON			(22)
-#define CORGI_GPIO_SD_PWR			(33)
+#define CORGI_GPIO_ADS7846_CS		(24) /* ADS7846 Chip Select */
+#define CORGI_GPIO_SD_PWR			(33) /* MMC/SD Power */
 #define CORGI_GPIO_CHRG_ON			(38)
 #define CORGI_GPIO_DISCHARGE_ON		(42)
-#define CORGI_GPIO_HSYNC			(44)
+#define CORGI_GPIO_HSYNC			(44) /* LCD HSync Pulse */
 #define CORGI_GPIO_USB_PULLUP		(45)
 
 
--- linux-2.6.10/arch/arm/mach-pxa/corgi.c~corgi_ssp-r6.patch
+++ linux-2.6.10/arch/arm/mach-pxa/corgi.c
@@ -68,8 +68,14 @@
 	.resource	= corgi_scoop_resources,
 };
 
+static struct platform_device corgissp_device = {
+	.name		= "corgi-ssp",
+	.id		= -1,
+};
+
 static struct platform_device *devices[] __initdata = {
 	&corgiscoop_device,
+	&corgissp_device,
 };
 
 static struct sharpsl_flash_param_info sharpsl_flash_param;

