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.
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
);
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
)
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
);
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
);
138 int corgi_ssp_max1111_get(ulong data
)
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
);
152 ssp_write_word(&corgi_ssp_dev
,data
);
153 ssp_read_word(&corgi_ssp_dev
); /* null read */
156 ssp_write_word(&corgi_ssp_dev
,0);
157 voltage1
=ssp_read_word(&corgi_ssp_dev
);
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)
172 voltage
= ((voltage1
<< 2) & 0xfc) | ((voltage2
>> 6) & 0x03);
177 EXPORT_SYMBOL(corgi_ssp_max1111_get
);
182 int __init
corgi_ssp_probe(struct device
*dev
)
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);
197 printk(KERN_ERR
"Unable to register SSP handler!\n");
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
);
207 static int corgi_ssp_remove(struct device
*dev
)
209 ssp_exit(&corgi_ssp_dev
);
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
);
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
);
234 static struct device_driver corgissp_driver
= {
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
);