0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/delay.h>
0012 #include <linux/errno.h>
0013 #include <linux/init.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/sched.h>
0018 #include <linux/io.h>
0019
0020 #include <mach/hardware.h>
0021 #include <mach/jornada720.h>
0022 #include <asm/hardware/ssp.h>
0023
0024 static DEFINE_SPINLOCK(jornada_ssp_lock);
0025 static unsigned long jornada_ssp_flags;
0026
0027
0028
0029
0030
0031
0032
0033 inline u8 jornada_ssp_reverse(u8 byte)
0034 {
0035 return
0036 ((0x80 & byte) >> 7) |
0037 ((0x40 & byte) >> 5) |
0038 ((0x20 & byte) >> 3) |
0039 ((0x10 & byte) >> 1) |
0040 ((0x08 & byte) << 1) |
0041 ((0x04 & byte) << 3) |
0042 ((0x02 & byte) << 5) |
0043 ((0x01 & byte) << 7);
0044 };
0045 EXPORT_SYMBOL(jornada_ssp_reverse);
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 int jornada_ssp_byte(u8 byte)
0057 {
0058 int timeout = 400000;
0059 u16 ret;
0060
0061 while ((GPLR & GPIO_GPIO10)) {
0062 if (!--timeout) {
0063 printk(KERN_WARNING "SSP: timeout while waiting for transmit\n");
0064 return -ETIMEDOUT;
0065 }
0066 cpu_relax();
0067 }
0068
0069 ret = jornada_ssp_reverse(byte) << 8;
0070
0071 ssp_write_word(ret);
0072 ssp_read_word(&ret);
0073
0074 return jornada_ssp_reverse(ret);
0075 };
0076 EXPORT_SYMBOL(jornada_ssp_byte);
0077
0078
0079
0080
0081
0082
0083
0084 int jornada_ssp_inout(u8 byte)
0085 {
0086 int ret, i;
0087
0088
0089 if (byte != TXDUMMY) {
0090 ret = jornada_ssp_byte(byte);
0091
0092 if (ret != TXDUMMY) {
0093 for (i = 0; i < 256; i++)
0094 if (jornada_ssp_byte(TXDUMMY) == -1)
0095 break;
0096 return -ETIMEDOUT;
0097 }
0098 } else
0099 ret = jornada_ssp_byte(TXDUMMY);
0100
0101 return ret;
0102 };
0103 EXPORT_SYMBOL(jornada_ssp_inout);
0104
0105
0106
0107
0108
0109 void jornada_ssp_start(void)
0110 {
0111 spin_lock_irqsave(&jornada_ssp_lock, jornada_ssp_flags);
0112 GPCR = GPIO_GPIO25;
0113 udelay(50);
0114 return;
0115 };
0116 EXPORT_SYMBOL(jornada_ssp_start);
0117
0118
0119
0120
0121
0122 void jornada_ssp_end(void)
0123 {
0124 GPSR = GPIO_GPIO25;
0125 spin_unlock_irqrestore(&jornada_ssp_lock, jornada_ssp_flags);
0126 return;
0127 };
0128 EXPORT_SYMBOL(jornada_ssp_end);
0129
0130 static int jornada_ssp_probe(struct platform_device *dev)
0131 {
0132 int ret;
0133
0134 GPSR = GPIO_GPIO25;
0135
0136 ret = ssp_init();
0137
0138
0139 if (!ret) {
0140 printk(KERN_INFO "SSP: device initialized with irq\n");
0141 return ret;
0142 }
0143
0144 printk(KERN_WARNING "SSP: initialization failed, trying non-irq solution \n");
0145
0146
0147 Ser4MCCR0 = 0;
0148 Ser4SSCR0 = 0x0387;
0149 Ser4SSCR1 = 0x18;
0150
0151
0152 ssp_flush();
0153
0154
0155 jornada_ssp_start();
0156
0157
0158 ret = jornada_ssp_inout(GETBRIGHTNESS);
0159
0160
0161 if (ret == TXDUMMY)
0162 jornada_ssp_inout(TXDUMMY);
0163
0164 jornada_ssp_end();
0165
0166
0167 if (ret == -ETIMEDOUT) {
0168 printk(KERN_WARNING "SSP: attempts failed, bailing\n");
0169 ssp_exit();
0170 return -ENODEV;
0171 }
0172
0173
0174 printk(KERN_INFO "SSP: device initialized\n");
0175 return 0;
0176 };
0177
0178 static int jornada_ssp_remove(struct platform_device *dev)
0179 {
0180
0181
0182 GPSR = GPIO_GPIO25;
0183 ssp_exit();
0184 return 0;
0185 };
0186
0187 struct platform_driver jornadassp_driver = {
0188 .probe = jornada_ssp_probe,
0189 .remove = jornada_ssp_remove,
0190 .driver = {
0191 .name = "jornada_ssp",
0192 },
0193 };
0194
0195 static int __init jornada_ssp_init(void)
0196 {
0197 return platform_driver_register(&jornadassp_driver);
0198 }
0199
0200 module_init(jornada_ssp_init);