Linux-2.6.12-rc2
[safe/jmp/linux-2.6] / arch / arm / mach-sa1100 / ssp.c
1 /*
2  *  linux/arch/arm/mach-sa1100/ssp.c
3  *
4  *  Copyright (C) 2003 Russell King.
5  *
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.
9  *
10  *  Generic SSP driver.  This provides the generic core for simple
11  *  IO-based SSP applications.
12  */
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/sched.h>
16 #include <linux/errno.h>
17 #include <linux/interrupt.h>
18 #include <linux/ioport.h>
19 #include <linux/init.h>
20
21 #include <asm/io.h>
22 #include <asm/irq.h>
23 #include <asm/hardware.h>
24 #include <asm/hardware/ssp.h>
25
26 static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
27 {
28         unsigned int status = Ser4SSSR;
29
30         if (status & SSSR_ROR) {
31                 printk(KERN_WARNING "SSP: receiver overrun\n");
32         }
33
34         Ser4SSSR = SSSR_ROR;
35
36         return status ? IRQ_HANDLED : IRQ_NONE;
37 }
38
39 /**
40  * ssp_write_word - write a word to the SSP port
41  * @data: 16-bit, MSB justified data to write.
42  *
43  * Wait for a free entry in the SSP transmit FIFO, and write a data
44  * word to the SSP port.  Wait for the SSP port to start sending
45  * the data.
46  *
47  * The caller is expected to perform the necessary locking.
48  *
49  * Returns:
50  *   %-ETIMEDOUT        timeout occurred (for future)
51  *   0                  success
52  */
53 int ssp_write_word(u16 data)
54 {
55         while (!(Ser4SSSR & SSSR_TNF))
56                 cpu_relax();
57
58         Ser4SSDR = data;
59
60         while (!(Ser4SSSR & SSSR_BSY))
61                 cpu_relax();
62
63         return 0;
64 }
65
66 /**
67  * ssp_read_word - read a word from the SSP port
68  *
69  * Wait for a data word in the SSP receive FIFO, and return the
70  * received data.  Data is LSB justified.
71  *
72  * Note: Currently, if data is not expected to be received, this
73  * function will wait for ever.
74  *
75  * The caller is expected to perform the necessary locking.
76  *
77  * Returns:
78  *   %-ETIMEDOUT        timeout occurred (for future)
79  *   16-bit data        success
80  */
81 int ssp_read_word(void)
82 {
83         while (!(Ser4SSSR & SSSR_RNE))
84                 cpu_relax();
85
86         return Ser4SSDR;
87 }
88
89 /**
90  * ssp_flush - flush the transmit and receive FIFOs
91  *
92  * Wait for the SSP to idle, and ensure that the receive FIFO
93  * is empty.
94  *
95  * The caller is expected to perform the necessary locking.
96  */
97 void ssp_flush(void)
98 {
99         do {
100                 while (Ser4SSSR & SSSR_RNE) {
101                         (void) Ser4SSDR;
102                 }
103         } while (Ser4SSSR & SSSR_BSY);
104 }
105
106 /**
107  * ssp_enable - enable the SSP port
108  *
109  * Turn on the SSP port.
110  */
111 void ssp_enable(void)
112 {
113         Ser4SSCR0 |= SSCR0_SSE;
114 }
115
116 /**
117  * ssp_disable - shut down the SSP port
118  *
119  * Turn off the SSP port, optionally powering it down.
120  */
121 void ssp_disable(void)
122 {
123         Ser4SSCR0 &= ~SSCR0_SSE;
124 }
125
126 /**
127  * ssp_save_state - save the SSP configuration
128  * @ssp: pointer to structure to save SSP configuration
129  *
130  * Save the configured SSP state for suspend.
131  */
132 void ssp_save_state(struct ssp_state *ssp)
133 {
134         ssp->cr0 = Ser4SSCR0;
135         ssp->cr1 = Ser4SSCR1;
136
137         Ser4SSCR0 &= ~SSCR0_SSE;
138 }
139
140 /**
141  * ssp_restore_state - restore a previously saved SSP configuration
142  * @ssp: pointer to configuration saved by ssp_save_state
143  *
144  * Restore the SSP configuration saved previously by ssp_save_state.
145  */
146 void ssp_restore_state(struct ssp_state *ssp)
147 {
148         Ser4SSSR = SSSR_ROR;
149
150         Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE;
151         Ser4SSCR1 = ssp->cr1;
152         Ser4SSCR0 = ssp->cr0;
153 }
154
155 /**
156  * ssp_init - setup the SSP port
157  *
158  * initialise and claim resources for the SSP port.
159  *
160  * Returns:
161  *   %-ENODEV   if the SSP port is unavailable
162  *   %-EBUSY    if the resources are already in use
163  *   %0         on success
164  */
165 int ssp_init(void)
166 {
167         int ret;
168
169         if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE))
170                 return -ENODEV;
171
172         if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) {
173                 return -EBUSY;
174         }
175
176         Ser4SSSR = SSSR_ROR;
177
178         ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL);
179         if (ret)
180                 goto out_region;
181
182         return 0;
183
184  out_region:
185         release_mem_region(__PREG(Ser4SSCR0), 0x18);
186         return ret;
187 }
188
189 /**
190  * ssp_exit - undo the effects of ssp_init
191  *
192  * release and free resources for the SSP port.
193  */
194 void ssp_exit(void)
195 {
196         Ser4SSCR0 &= ~SSCR0_SSE;
197
198         free_irq(IRQ_Ser4SSP, NULL);
199         release_mem_region(__PREG(Ser4SSCR0), 0x18);
200 }
201
202 MODULE_AUTHOR("Russell King");
203 MODULE_DESCRIPTION("SA11x0 SSP PIO driver");
204 MODULE_LICENSE("GPL");
205
206 EXPORT_SYMBOL(ssp_write_word);
207 EXPORT_SYMBOL(ssp_read_word);
208 EXPORT_SYMBOL(ssp_flush);
209 EXPORT_SYMBOL(ssp_enable);
210 EXPORT_SYMBOL(ssp_disable);
211 EXPORT_SYMBOL(ssp_save_state);
212 EXPORT_SYMBOL(ssp_restore_state);
213 EXPORT_SYMBOL(ssp_init);
214 EXPORT_SYMBOL(ssp_exit);