Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
jornada720_ssp.c
Go to the documentation of this file.
1 
14 #include <linux/delay.h>
15 #include <linux/errno.h>
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/sched.h>
21 #include <linux/io.h>
22 
23 #include <mach/hardware.h>
24 #include <mach/jornada720.h>
25 #include <asm/hardware/ssp.h>
26 
27 static DEFINE_SPINLOCK(jornada_ssp_lock);
28 static unsigned long jornada_ssp_flags;
29 
37 {
38  return
39  ((0x80 & byte) >> 7) |
40  ((0x40 & byte) >> 5) |
41  ((0x20 & byte) >> 3) |
42  ((0x10 & byte) >> 1) |
43  ((0x08 & byte) << 1) |
44  ((0x04 & byte) << 3) |
45  ((0x02 & byte) << 5) |
46  ((0x01 & byte) << 7);
47 };
49 
60 {
61  int timeout = 400000;
62  u16 ret;
63 
64  while ((GPLR & GPIO_GPIO10)) {
65  if (!--timeout) {
66  printk(KERN_WARNING "SSP: timeout while waiting for transmit\n");
67  return -ETIMEDOUT;
68  }
69  cpu_relax();
70  }
71 
72  ret = jornada_ssp_reverse(byte) << 8;
73 
74  ssp_write_word(ret);
75  ssp_read_word(&ret);
76 
77  return jornada_ssp_reverse(ret);
78 };
80 
88 {
89  int ret, i;
90 
91  /* true means command byte */
92  if (byte != TXDUMMY) {
93  ret = jornada_ssp_byte(byte);
94  /* Proper return to commands is TxDummy */
95  if (ret != TXDUMMY) {
96  for (i = 0; i < 256; i++)/* flushing bus */
97  if (jornada_ssp_byte(TXDUMMY) == -1)
98  break;
99  return -ETIMEDOUT;
100  }
101  } else /* Exchange TxDummy for data */
102  ret = jornada_ssp_byte(TXDUMMY);
103 
104  return ret;
105 };
107 
113 {
114  spin_lock_irqsave(&jornada_ssp_lock, jornada_ssp_flags);
115  GPCR = GPIO_GPIO25;
116  udelay(50);
117  return;
118 };
120 
125 void jornada_ssp_end(void)
126 {
127  GPSR = GPIO_GPIO25;
128  spin_unlock_irqrestore(&jornada_ssp_lock, jornada_ssp_flags);
129  return;
130 };
132 
133 static int __devinit jornada_ssp_probe(struct platform_device *dev)
134 {
135  int ret;
136 
137  GPSR = GPIO_GPIO25;
138 
139  ret = ssp_init();
140 
141  /* worked fine, lets not bother with anything else */
142  if (!ret) {
143  printk(KERN_INFO "SSP: device initialized with irq\n");
144  return ret;
145  }
146 
147  printk(KERN_WARNING "SSP: initialization failed, trying non-irq solution \n");
148 
149  /* init of Serial 4 port */
150  Ser4MCCR0 = 0;
151  Ser4SSCR0 = 0x0387;
152  Ser4SSCR1 = 0x18;
153 
154  /* clear out any left over data */
155  ssp_flush();
156 
157  /* enable MCU */
159 
160  /* see if return value makes sense */
162 
163  /* seems like it worked, just feed it with TxDummy to get rid of data */
164  if (ret == TXDUMMY)
166 
167  jornada_ssp_end();
168 
169  /* failed, lets just kill everything */
170  if (ret == -ETIMEDOUT) {
171  printk(KERN_WARNING "SSP: attempts failed, bailing\n");
172  ssp_exit();
173  return -ENODEV;
174  }
175 
176  /* all fine */
177  printk(KERN_INFO "SSP: device initialized\n");
178  return 0;
179 };
180 
181 static int jornada_ssp_remove(struct platform_device *dev)
182 {
183  /* Note that this doesn't actually remove the driver, since theres nothing to remove
184  * It just makes sure everything is turned off */
185  GPSR = GPIO_GPIO25;
186  ssp_exit();
187  return 0;
188 };
189 
191  .probe = jornada_ssp_probe,
192  .remove = jornada_ssp_remove,
193  .driver = {
194  .name = "jornada_ssp",
195  },
196 };
197 
198 static int __init jornada_ssp_init(void)
199 {
200  return platform_driver_register(&jornadassp_driver);
201 }
202 
203 module_init(jornada_ssp_init);