Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / arm / mach-pxa / corgi_ssp.c
blob8ccffba0018fa5f1ef5d607c0be447ffc1dacd4c
1 /*
2 * SSP control code for Sharp Corgi devices
4 * Copyright (c) 2004 Richard Purdie
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/sched.h>
16 #include <linux/slab.h>
17 #include <linux/delay.h>
18 #include <linux/device.h>
19 #include <asm/hardware.h>
21 #include <asm/arch/ssp.h>
22 #include <asm/arch/corgi.h>
23 #include <asm/arch/pxa-regs.h>
25 static spinlock_t corgi_ssp_lock = SPIN_LOCK_UNLOCKED;
26 static struct ssp_dev corgi_ssp_dev;
27 static struct ssp_state corgi_ssp_state;
30 * There are three devices connected to the SSP interface:
31 * 1. A touchscreen controller (TI ADS7846 compatible)
32 * 2. An LCD contoller (with some Backlight functionality)
33 * 3. A battery moinitoring IC (Maxim MAX1111)
35 * Each device uses a different speed/mode of communication.
37 * The touchscreen is very sensitive and the most frequently used
38 * so the port is left configured for this.
40 * Devices are selected using Chip Selects on GPIOs.
44 * ADS7846 Routines
46 unsigned long corgi_ssp_ads7846_putget(ulong data)
48 unsigned long ret,flag;
50 spin_lock_irqsave(&corgi_ssp_lock, flag);
51 GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
53 ssp_write_word(&corgi_ssp_dev,data);
54 ret = ssp_read_word(&corgi_ssp_dev);
56 GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
57 spin_unlock_irqrestore(&corgi_ssp_lock, flag);
59 return ret;
63 * NOTE: These functions should always be called in interrupt context
64 * and use the _lock and _unlock functions. They are very time sensitive.
66 void corgi_ssp_ads7846_lock(void)
68 spin_lock(&corgi_ssp_lock);
69 GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
72 void corgi_ssp_ads7846_unlock(void)
74 GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
75 spin_unlock(&corgi_ssp_lock);
78 void corgi_ssp_ads7846_put(ulong data)
80 ssp_write_word(&corgi_ssp_dev,data);
83 unsigned long corgi_ssp_ads7846_get(void)
85 return ssp_read_word(&corgi_ssp_dev);
88 EXPORT_SYMBOL(corgi_ssp_ads7846_putget);
89 EXPORT_SYMBOL(corgi_ssp_ads7846_lock);
90 EXPORT_SYMBOL(corgi_ssp_ads7846_unlock);
91 EXPORT_SYMBOL(corgi_ssp_ads7846_put);
92 EXPORT_SYMBOL(corgi_ssp_ads7846_get);
96 * LCD/Backlight Routines
98 unsigned long corgi_ssp_dac_put(ulong data)
100 unsigned long flag;
102 spin_lock_irqsave(&corgi_ssp_lock, flag);
103 GPCR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
105 ssp_disable(&corgi_ssp_dev);
106 ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), SSCR1_SPH, 0, SSCR0_SerClkDiv(76));
107 ssp_enable(&corgi_ssp_dev);
109 ssp_write_word(&corgi_ssp_dev,data);
110 /* Read null data back from device to prevent SSP overflow */
111 ssp_read_word(&corgi_ssp_dev);
113 ssp_disable(&corgi_ssp_dev);
114 ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
115 ssp_enable(&corgi_ssp_dev);
116 GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
117 spin_unlock_irqrestore(&corgi_ssp_lock, flag);
119 return 0;
122 void corgi_ssp_lcdtg_send(u8 adrs, u8 data)
124 corgi_ssp_dac_put(((adrs & 0x07) << 5) | (data & 0x1f));
127 void corgi_ssp_blduty_set(int duty)
129 corgi_ssp_lcdtg_send(0x02,duty);
132 EXPORT_SYMBOL(corgi_ssp_lcdtg_send);
133 EXPORT_SYMBOL(corgi_ssp_blduty_set);
136 * Max1111 Routines
138 int corgi_ssp_max1111_get(ulong data)
140 unsigned long flag;
141 int voltage,voltage1,voltage2;
143 spin_lock_irqsave(&corgi_ssp_lock, flag);
144 GPCR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
145 ssp_disable(&corgi_ssp_dev);
146 ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(8));
147 ssp_enable(&corgi_ssp_dev);
149 udelay(1);
151 /* TB1/RB1 */
152 ssp_write_word(&corgi_ssp_dev,data);
153 ssp_read_word(&corgi_ssp_dev); /* null read */
155 /* TB12/RB2 */
156 ssp_write_word(&corgi_ssp_dev,0);
157 voltage1=ssp_read_word(&corgi_ssp_dev);
159 /* TB13/RB3*/
160 ssp_write_word(&corgi_ssp_dev,0);
161 voltage2=ssp_read_word(&corgi_ssp_dev);
163 ssp_disable(&corgi_ssp_dev);
164 ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
165 ssp_enable(&corgi_ssp_dev);
166 GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
167 spin_unlock_irqrestore(&corgi_ssp_lock, flag);
169 if (voltage1 & 0xc0 || voltage2 & 0x3f)
170 voltage = -1;
171 else
172 voltage = ((voltage1 << 2) & 0xfc) | ((voltage2 >> 6) & 0x03);
174 return voltage;
177 EXPORT_SYMBOL(corgi_ssp_max1111_get);
180 * Support Routines
182 int __init corgi_ssp_probe(struct device *dev)
184 int ret;
186 /* Chip Select - Disable All */
187 GPDR0 |= GPIO_bit(CORGI_GPIO_LCDCON_CS); /* output */
188 GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */
189 GPDR0 |= GPIO_bit(CORGI_GPIO_MAX1111_CS); /* output */
190 GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
191 GPDR0 |= GPIO_bit(CORGI_GPIO_ADS7846_CS); /* output */
192 GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/
194 ret=ssp_init(&corgi_ssp_dev,1);
196 if (ret)
197 printk(KERN_ERR "Unable to register SSP handler!\n");
198 else {
199 ssp_disable(&corgi_ssp_dev);
200 ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
201 ssp_enable(&corgi_ssp_dev);
204 return ret;
207 static int corgi_ssp_remove(struct device *dev)
209 ssp_exit(&corgi_ssp_dev);
210 return 0;
213 static int corgi_ssp_suspend(struct device *dev, pm_message_t state, u32 level)
215 if (level == SUSPEND_POWER_DOWN) {
216 ssp_flush(&corgi_ssp_dev);
217 ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
219 return 0;
222 static int corgi_ssp_resume(struct device *dev, u32 level)
224 if (level == RESUME_POWER_ON) {
225 GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */
226 GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
227 GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/
228 ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
229 ssp_enable(&corgi_ssp_dev);
231 return 0;
234 static struct device_driver corgissp_driver = {
235 .name = "corgi-ssp",
236 .bus = &platform_bus_type,
237 .probe = corgi_ssp_probe,
238 .remove = corgi_ssp_remove,
239 .suspend = corgi_ssp_suspend,
240 .resume = corgi_ssp_resume,
243 int __init corgi_ssp_init(void)
245 return driver_register(&corgissp_driver);
248 arch_initcall(corgi_ssp_init);