0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/kernel.h>
0012 #include <linux/sched.h>
0013 #include <linux/errno.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/ioport.h>
0016 #include <linux/init.h>
0017 #include <linux/io.h>
0018
0019 #include <mach/hardware.h>
0020 #include <mach/irqs.h>
0021 #include <asm/hardware/ssp.h>
0022
0023 #define TIMEOUT 100000
0024
0025 static irqreturn_t ssp_interrupt(int irq, void *dev_id)
0026 {
0027 unsigned int status = Ser4SSSR;
0028
0029 if (status & SSSR_ROR)
0030 printk(KERN_WARNING "SSP: receiver overrun\n");
0031
0032 Ser4SSSR = SSSR_ROR;
0033
0034 return status ? IRQ_HANDLED : IRQ_NONE;
0035 }
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 int ssp_write_word(u16 data)
0052 {
0053 int timeout = TIMEOUT;
0054
0055 while (!(Ser4SSSR & SSSR_TNF)) {
0056 if (!--timeout)
0057 return -ETIMEDOUT;
0058 cpu_relax();
0059 }
0060
0061 Ser4SSDR = data;
0062
0063 timeout = TIMEOUT;
0064 while (!(Ser4SSSR & SSSR_BSY)) {
0065 if (!--timeout)
0066 return -ETIMEDOUT;
0067 cpu_relax();
0068 }
0069
0070 return 0;
0071 }
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088 int ssp_read_word(u16 *data)
0089 {
0090 int timeout = TIMEOUT;
0091
0092 while (!(Ser4SSSR & SSSR_RNE)) {
0093 if (!--timeout)
0094 return -ETIMEDOUT;
0095 cpu_relax();
0096 }
0097
0098 *data = (u16)Ser4SSDR;
0099
0100 return 0;
0101 }
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 int ssp_flush(void)
0116 {
0117 int timeout = TIMEOUT * 2;
0118
0119 do {
0120 while (Ser4SSSR & SSSR_RNE) {
0121 if (!--timeout)
0122 return -ETIMEDOUT;
0123 (void) Ser4SSDR;
0124 }
0125 if (!--timeout)
0126 return -ETIMEDOUT;
0127 } while (Ser4SSSR & SSSR_BSY);
0128
0129 return 0;
0130 }
0131
0132
0133
0134
0135
0136
0137 void ssp_enable(void)
0138 {
0139 Ser4SSCR0 |= SSCR0_SSE;
0140 }
0141
0142
0143
0144
0145
0146
0147 void ssp_disable(void)
0148 {
0149 Ser4SSCR0 &= ~SSCR0_SSE;
0150 }
0151
0152
0153
0154
0155
0156
0157
0158 void ssp_save_state(struct ssp_state *ssp)
0159 {
0160 ssp->cr0 = Ser4SSCR0;
0161 ssp->cr1 = Ser4SSCR1;
0162
0163 Ser4SSCR0 &= ~SSCR0_SSE;
0164 }
0165
0166
0167
0168
0169
0170
0171
0172 void ssp_restore_state(struct ssp_state *ssp)
0173 {
0174 Ser4SSSR = SSSR_ROR;
0175
0176 Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE;
0177 Ser4SSCR1 = ssp->cr1;
0178 Ser4SSCR0 = ssp->cr0;
0179 }
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 int ssp_init(void)
0192 {
0193 int ret;
0194
0195 if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE))
0196 return -ENODEV;
0197
0198 if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) {
0199 return -EBUSY;
0200 }
0201
0202 Ser4SSSR = SSSR_ROR;
0203
0204 ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL);
0205 if (ret)
0206 goto out_region;
0207
0208 return 0;
0209
0210 out_region:
0211 release_mem_region(__PREG(Ser4SSCR0), 0x18);
0212 return ret;
0213 }
0214
0215
0216
0217
0218
0219
0220 void ssp_exit(void)
0221 {
0222 Ser4SSCR0 &= ~SSCR0_SSE;
0223
0224 free_irq(IRQ_Ser4SSP, NULL);
0225 release_mem_region(__PREG(Ser4SSCR0), 0x18);
0226 }
0227
0228 MODULE_AUTHOR("Russell King");
0229 MODULE_DESCRIPTION("SA11x0 SSP PIO driver");
0230 MODULE_LICENSE("GPL");
0231
0232 EXPORT_SYMBOL(ssp_write_word);
0233 EXPORT_SYMBOL(ssp_read_word);
0234 EXPORT_SYMBOL(ssp_flush);
0235 EXPORT_SYMBOL(ssp_enable);
0236 EXPORT_SYMBOL(ssp_disable);
0237 EXPORT_SYMBOL(ssp_save_state);
0238 EXPORT_SYMBOL(ssp_restore_state);
0239 EXPORT_SYMBOL(ssp_init);
0240 EXPORT_SYMBOL(ssp_exit);