2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
16 * Copyright (C) 2006 infineon
17 * Copyright (C) 2007 John Crispin <blogic@openwrt.org>
21 // ### TO DO: general issues:
23 // - interrupt handling (direct/indirect)
24 // - pin/mux-handling (just overall concept due to project dependency)
25 // - multiple instances capability
26 // - slave functionality
28 #include <linux/module.h>
29 #include <linux/errno.h>
30 #include <linux/signal.h>
31 #include <linux/sched.h>
32 #include <linux/timer.h>
33 #include <linux/interrupt.h>
34 #include <linux/major.h>
35 #include <linux/string.h>
37 #include <linux/fcntl.h>
38 #include <linux/ptrace.h>
40 #include <linux/ioport.h>
41 #include <linux/init.h>
42 #include <linux/delay.h>
43 #include <linux/spinlock.h>
44 #include <linux/slab.h>
46 #include <asm/system.h>
49 #include <asm/uaccess.h>
50 #include <asm/bitops.h>
52 #include <linux/types.h>
53 #include <linux/kernel.h>
54 #include <linux/version.h>
56 #include <asm/ifxmips/ifxmips.h>
57 #include <asm/ifxmips/ifxmips_irq.h>
58 #include <asm/ifxmips/ifx_ssc_defines.h>
59 #include <asm/ifxmips/ifx_ssc.h>
61 /* allow the user to set the major device number */
65 * This is the per-channel data structure containing pointers, flags
66 * and variables for the port. This driver supports a maximum of PORT_CNT.
67 * isp is allocated in ifx_ssc_init() based on the chip version.
69 static struct ifx_ssc_port
*isp
;
71 /* other forward declarations */
72 static unsigned int ifx_ssc_get_kernel_clk (struct ifx_ssc_port
*info
);
73 static void tx_int (struct ifx_ssc_port
*);
75 extern unsigned int ifxmips_get_fpi_hz (void);
76 extern void mask_and_ack_ifxmips_irq (unsigned int irq_nr
);
78 static inline unsigned int
79 ifx_ssc_get_kernel_clk (struct ifx_ssc_port
*info
)
83 rmc
= (readl(IFXMIPS_SSC_CLC
) & IFX_CLC_RUN_DIVIDER_MASK
) >> IFX_CLC_RUN_DIVIDER_OFFSET
;
86 printk ("ifx_ssc_get_kernel_clk rmc==0 \n");
89 return ifxmips_get_fpi_hz () / rmc
;
93 #ifdef IFX_SSC_INT_USE_BH
95 * This routine is used by the interrupt handler to schedule
96 * processing in the software interrupt portion of the driver
97 * (also known as the "bottom half"). This can be called any
98 * number of times for any channel without harm.
101 ifx_ssc_sched_event (struct ifx_ssc_port
*info
, int event
)
103 info
->event
|= 1 << event
; /* remember what kind of event and who */
104 queue_task (&info
->tqueue
, &tq_cyclades
); /* it belongs to */
105 mark_bh (CYCLADES_BH
); /* then trigger event */
109 do_softint (void *private_
)
111 struct ifx_ssc_port
*info
= (struct ifx_ssc_port
*) private_
;
113 if (test_and_clear_bit (Cy_EVENT_HANGUP
, &info
->event
))
115 wake_up_interruptible (&info
->open_wait
);
116 info
->flags
&= ~(ASYNC_NORMAL_ACTIVE
| ASYNC_CALLOUT_ACTIVE
);
119 if (test_and_clear_bit (Cy_EVENT_OPEN_WAKEUP
, &info
->event
))
120 wake_up_interruptible (&info
->open_wait
);
122 if (test_and_clear_bit (Cy_EVENT_DELTA_WAKEUP
, &info
->event
))
123 wake_up_interruptible (&info
->delta_msr_wait
);
125 if (test_and_clear_bit (Cy_EVENT_WRITE_WAKEUP
, &info
->event
))
126 wake_up_interruptible (&tty
->write_wait
);
128 if (test_and_clear_bit (Cy_EVENT_SHUTDOWN_WAKEUP
, &info
->event
))
129 wake_up_interruptible (&info
->shutdown_wait
);
136 rx_int (struct ifx_ssc_port
*info
)
138 int fifo_fill_lev
, bytes_in_buf
, i
;
139 unsigned long tmp_val
;
140 unsigned long *tmp_ptr
;
141 unsigned int rx_valid_cnt
;
142 /* number of words waiting in the RX FIFO */
143 fifo_fill_lev
= (readl(IFXMIPS_SSC_FSTAT
) & IFX_SSC_FSTAT_RECEIVED_WORDS_MASK
) >> IFX_SSC_FSTAT_RECEIVED_WORDS_OFFSET
;
144 bytes_in_buf
= info
->rxbuf_end
- info
->rxbuf_ptr
;
145 // transfer with 32 bits per entry
146 while ((bytes_in_buf
>= 4) && (fifo_fill_lev
> 0)) {
147 tmp_ptr
= (unsigned long *) info
->rxbuf_ptr
;
148 *tmp_ptr
= readl(IFXMIPS_SSC_RB
);
149 info
->rxbuf_ptr
+= 4;
150 info
->stats
.rxBytes
+= 4;
155 // now do the rest as mentioned in STATE.RXBV
156 while ((bytes_in_buf
> 0) && (fifo_fill_lev
> 0)) {
157 rx_valid_cnt
= (readl(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_RX_BYTE_VALID_MASK
) >> IFX_SSC_STATE_RX_BYTE_VALID_OFFSET
;
158 if (rx_valid_cnt
== 0)
161 if (rx_valid_cnt
> bytes_in_buf
)
162 rx_valid_cnt
= bytes_in_buf
;
164 tmp_val
= readl(IFXMIPS_SSC_RB
);
166 for (i
= 0; i
< rx_valid_cnt
; i
++)
168 *info
->rxbuf_ptr
= (tmp_val
>> (8 * (rx_valid_cnt
- i
- 1))) & 0xff;
172 info
->stats
.rxBytes
+= rx_valid_cnt
;
175 // check if transfer is complete
176 if (info
->rxbuf_ptr
>= info
->rxbuf_end
)
178 disable_irq(IFXMIPS_SSC_RIR
);
179 wake_up_interruptible (&info
->rwait
);
180 } else if ((info
->opts
.modeRxTx
== IFX_SSC_MODE_RX
) && (readl(IFXMIPS_SSC_RXCNT
) == 0))
182 if (info
->rxbuf_end
- info
->rxbuf_ptr
< IFX_SSC_RXREQ_BLOCK_SIZE
)
183 writel((info
->rxbuf_end
- info
->rxbuf_ptr
) << IFX_SSC_RXREQ_RXCOUNT_OFFSET
, IFXMIPS_SSC_RXREQ
);
185 writel(IFX_SSC_RXREQ_BLOCK_SIZE
<< IFX_SSC_RXREQ_RXCOUNT_OFFSET
, IFXMIPS_SSC_RXREQ
);
190 tx_int (struct ifx_ssc_port
*info
)
193 int fifo_space
, fill
, i
;
194 fifo_space
= ((readl(IFXMIPS_SSC_ID
) & IFX_SSC_PERID_TXFS_MASK
) >> IFX_SSC_PERID_TXFS_OFFSET
)
195 - ((readl(IFXMIPS_SSC_FSTAT
) & IFX_SSC_FSTAT_TRANSMIT_WORDS_MASK
) >> IFX_SSC_FSTAT_TRANSMIT_WORDS_OFFSET
);
200 fill
= info
->txbuf_end
- info
->txbuf_ptr
;
202 if (fill
> fifo_space
* 4)
203 fill
= fifo_space
* 4;
205 for (i
= 0; i
< fill
/ 4; i
++)
207 // at first 32 bit access
208 writel(*(UINT32
*) info
->txbuf_ptr
, IFXMIPS_SSC_TB
);
209 info
->txbuf_ptr
+= 4;
212 fifo_space
-= fill
/ 4;
213 info
->stats
.txBytes
+= fill
& ~0x3;
215 if ((fifo_space
> 0) & (fill
> 1))
217 // trailing 16 bit access
218 WRITE_PERIPHERAL_REGISTER_16 (*(UINT16
*) info
->txbuf_ptr
, info
->mapbase
+ IFX_SSC_TB
);
219 info
->txbuf_ptr
+= 2;
220 info
->stats
.txBytes
+= 2;
225 if ((fifo_space
> 0) & (fill
> 0))
227 // trailing 8 bit access
228 WRITE_PERIPHERAL_REGISTER_8 (*(UINT8
*) info
->txbuf_ptr
, info
->mapbase
+ IFX_SSC_TB
);
230 info
->stats
.txBytes
++;
233 // check if transmission complete
234 if (info
->txbuf_ptr
>= info
->txbuf_end
)
236 disable_irq(IFXMIPS_SSC_TIR
);
244 ifx_ssc_rx_int (int irq
, void *dev_id
)
246 struct ifx_ssc_port
*info
= (struct ifx_ssc_port
*) dev_id
;
253 ifx_ssc_tx_int (int irq
, void *dev_id
)
255 struct ifx_ssc_port
*info
= (struct ifx_ssc_port
*) dev_id
;
262 ifx_ssc_err_int (int irq
, void *dev_id
)
264 struct ifx_ssc_port
*info
= (struct ifx_ssc_port
*) dev_id
;
266 unsigned int write_back
= 0;
269 local_irq_save (flags
);
270 state
= readl(IFXMIPS_SSC_STATE
);
272 if ((state
& IFX_SSC_STATE_RX_UFL
) != 0) {
273 info
->stats
.rxUnErr
++;
274 write_back
|= IFX_SSC_WHBSTATE_CLR_RX_UFL_ERROR
;
277 if ((state
& IFX_SSC_STATE_RX_OFL
) != 0) {
278 info
->stats
.rxOvErr
++;
279 write_back
|= IFX_SSC_WHBSTATE_CLR_RX_OFL_ERROR
;
282 if ((state
& IFX_SSC_STATE_TX_OFL
) != 0) {
283 info
->stats
.txOvErr
++;
284 write_back
|= IFX_SSC_WHBSTATE_CLR_TX_OFL_ERROR
;
287 if ((state
& IFX_SSC_STATE_TX_UFL
) != 0) {
288 info
->stats
.txUnErr
++;
289 write_back
|= IFX_SSC_WHBSTATE_CLR_TX_UFL_ERROR
;
292 if ((state
& IFX_SSC_STATE_MODE_ERR
) != 0) {
293 info
->stats
.modeErr
++;
294 write_back
|= IFX_SSC_WHBSTATE_CLR_MODE_ERROR
;
298 writel(write_back
, IFXMIPS_SSC_WHBSTATE
);
300 local_irq_restore (flags
);
306 ifx_ssc_abort (struct ifx_ssc_port
*info
)
311 local_irq_save (flags
);
313 disable_irq(IFXMIPS_SSC_RIR
);
314 disable_irq(IFXMIPS_SSC_TIR
);
315 disable_irq(IFXMIPS_SSC_EIR
);
317 local_irq_restore (flags
);
319 // disable SSC (also aborts a receive request!)
320 // ### TO DO: Perhaps it's better to abort after the receiption of a
321 // complete word. The disable cuts the transmission immediatly and
322 // releases the chip selects. This could result in unpredictable
323 // behavior of connected external devices!
324 enabled
= (readl(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_IS_ENABLED
) != 0;
325 writel(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
328 writel(IFX_SSC_XFCON_FIFO_FLUSH
, IFXMIPS_SSC_TXFCON
);
329 writel(IFX_SSC_XFCON_FIFO_FLUSH
, IFXMIPS_SSC_RXFCON
);
332 if (info
->txbuf
!= NULL
)
338 // wakeup read process
339 if (info
->rxbuf
!= NULL
)
340 wake_up_interruptible (&info
->rwait
);
342 // clear pending int's
343 mask_and_ack_ifxmips_irq(IFXMIPS_SSC_RIR
);
344 mask_and_ack_ifxmips_irq(IFXMIPS_SSC_TIR
);
345 mask_and_ack_ifxmips_irq(IFXMIPS_SSC_EIR
);
348 writel(IFX_SSC_WHBSTATE_CLR_ALL_ERROR
, IFXMIPS_SSC_WHBSTATE
);
351 writel(IFX_SSC_WHBSTATE_SET_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
356 * This routine is called whenever a port is opened. It enforces
357 * exclusive opening of a port and enables interrupts, etc.
360 ifx_ssc_open (struct inode
*inode
, struct file
*filp
)
362 struct ifx_ssc_port
*info
;
366 if ((inode
== (struct inode
*) 0) || (inode
== (struct inode
*) 1)) {
370 line
= MINOR (filp
->f_dentry
->d_inode
->i_rdev
);
373 /* don't open more minor devices than we can support */
374 if (line
< 0 || line
>= PORT_CNT
)
380 if (info
->port_is_open
!= 0)
382 info
->port_is_open
++;
384 disable_irq(IFXMIPS_SSC_RIR
);
385 disable_irq(IFXMIPS_SSC_TIR
);
386 disable_irq(IFXMIPS_SSC_EIR
);
388 /* Flush and enable TX/RX FIFO */
389 writel((IFX_SSC_DEF_TXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_FLUSH
| IFX_SSC_XFCON_FIFO_ENABLE
, IFXMIPS_SSC_TXFCON
);
390 writel((IFX_SSC_DEF_RXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_FLUSH
| IFX_SSC_XFCON_FIFO_ENABLE
, IFXMIPS_SSC_RXFCON
);
392 /* logically flush the software FIFOs */
396 /* clear all error bits */
397 writel(IFX_SSC_WHBSTATE_CLR_ALL_ERROR
, IFXMIPS_SSC_WHBSTATE
);
399 // clear pending interrupts
400 mask_and_ack_ifxmips_irq(IFXMIPS_SSC_RIR
);
401 mask_and_ack_ifxmips_irq(IFXMIPS_SSC_TIR
);
402 mask_and_ack_ifxmips_irq(IFXMIPS_SSC_EIR
);
404 writel(IFX_SSC_WHBSTATE_SET_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
408 EXPORT_SYMBOL(ifx_ssc_open
);
411 ifx_ssc_close (struct inode
*inode
, struct file
*filp
)
413 struct ifx_ssc_port
*info
;
416 if ((inode
== (struct inode
*) 0) || (inode
== (struct inode
*) 1))
419 idx
= MINOR (filp
->f_dentry
->d_inode
->i_rdev
);
421 if (idx
< 0 || idx
>= PORT_CNT
)
428 writel(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
432 info
->port_is_open
--;
436 EXPORT_SYMBOL(ifx_ssc_close
);
439 ifx_ssc_read_helper_poll (struct ifx_ssc_port
*info
, char *buf
, size_t len
, int from_kernel
)
444 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_TX
)
446 local_irq_save (flags
);
447 info
->rxbuf_ptr
= info
->rxbuf
;
448 info
->rxbuf_end
= info
->rxbuf
+ len
;
449 local_irq_restore (flags
);
450 /* Vinetic driver always works in IFX_SSC_MODE_RXTX */
451 /* TXRX in poll mode */
452 while (info
->rxbuf_ptr
< info
->rxbuf_end
)
454 if (info
->txbuf_ptr
< info
->txbuf_end
)
460 ret_val
= info
->rxbuf_ptr
- info
->rxbuf
;
466 ifx_ssc_read_helper (struct ifx_ssc_port
*info
, char *buf
, size_t len
, int from_kernel
)
470 DECLARE_WAITQUEUE (wait
, current
);
472 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_TX
)
475 local_irq_save (flags
);
476 info
->rxbuf_ptr
= info
->rxbuf
;
477 info
->rxbuf_end
= info
->rxbuf
+ len
;
479 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_RXTX
)
481 if ((info
->txbuf
== NULL
) || (info
->txbuf
!= info
->txbuf_ptr
) || (info
->txbuf_end
!= len
+ info
->txbuf
))
483 local_irq_restore (flags
);
484 printk ("IFX SSC - %s: write must be called before calling " "read in combined RX/TX!\n", __func__
);
488 local_irq_restore(flags
);
491 if (info
->txbuf_ptr
< info
->txbuf_end
)
492 enable_irq(IFXMIPS_SSC_TIR
);
494 enable_irq(IFXMIPS_SSC_RIR
);
496 local_irq_restore(flags
);
497 if (readl(IFXMIPS_SSC_RXCNT
) & IFX_SSC_RXCNT_TODO_MASK
)
499 enable_irq(IFXMIPS_SSC_RIR
);
500 if (len
< IFX_SSC_RXREQ_BLOCK_SIZE
)
501 writel(len
<< IFX_SSC_RXREQ_RXCOUNT_OFFSET
, IFXMIPS_SSC_RXREQ
);
503 writel(IFX_SSC_RXREQ_BLOCK_SIZE
<< IFX_SSC_RXREQ_RXCOUNT_OFFSET
, IFXMIPS_SSC_RXREQ
);
506 __add_wait_queue (&info
->rwait
, &wait
);
507 set_current_state (TASK_INTERRUPTIBLE
);
510 local_irq_save (flags
);
511 if (info
->rxbuf_ptr
>= info
->rxbuf_end
)
514 local_irq_restore (flags
);
516 if (signal_pending (current
))
518 ret_val
= -ERESTARTSYS
;
524 ret_val
= info
->rxbuf_ptr
- info
->rxbuf
;
525 local_irq_restore (flags
);
528 current
->state
= TASK_RUNNING
;
529 __remove_wait_queue (&info
->rwait
, &wait
);
535 ifx_ssc_write_helper (struct ifx_ssc_port
*info
, const char *buf
,
536 size_t len
, int from_kernel
)
538 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_RX
)
541 info
->txbuf_ptr
= info
->txbuf
;
542 info
->txbuf_end
= len
+ info
->txbuf
;
543 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_TX
)
546 if (info
->txbuf_ptr
< info
->txbuf_end
)
548 enable_irq(IFXMIPS_SSC_TIR
);
556 ifx_ssc_kread (int port
, char *kbuf
, size_t len
)
558 struct ifx_ssc_port
*info
;
561 if (port
< 0 || port
>= PORT_CNT
)
569 if (info
->rxbuf
!= NULL
)
571 printk ("SSC device busy\n");
576 if (info
->rxbuf
== NULL
)
578 printk ("SSC device error\n");
582 ret_val
= ifx_ssc_read_helper_poll (info
, kbuf
, len
, 1);
585 disable_irq(IFXMIPS_SSC_RIR
);
589 EXPORT_SYMBOL(ifx_ssc_kread
);
592 ifx_ssc_kwrite (int port
, const char *kbuf
, size_t len
)
594 struct ifx_ssc_port
*info
;
597 if (port
< 0 || port
>= PORT_CNT
)
605 // check if transmission in progress
606 if (info
->txbuf
!= NULL
)
609 info
->txbuf
= (char *) kbuf
;
611 ret_val
= ifx_ssc_write_helper (info
, info
->txbuf
, len
, 1);
618 EXPORT_SYMBOL(ifx_ssc_kwrite
);
621 ifx_ssc_read (struct file
*filp
, char *ubuf
, size_t len
, loff_t
* off
)
625 struct ifx_ssc_port
*info
;
627 idx
= MINOR (filp
->f_dentry
->d_inode
->i_rdev
);
630 if (info
->rxbuf
!= NULL
)
633 info
->rxbuf
= kmalloc (len
+ 3, GFP_KERNEL
);
634 if (info
->rxbuf
== NULL
)
637 ret_val
= ifx_ssc_read_helper (info
, info
->rxbuf
, len
, 0);
638 if (copy_to_user ((void *) ubuf
, info
->rxbuf
, ret_val
) != 0)
641 disable_irq(IFXMIPS_SSC_RIR
);
650 ifx_ssc_write (struct file
*filp
, const char *ubuf
, size_t len
, loff_t
* off
)
653 struct ifx_ssc_port
*info
;
659 idx
= MINOR (filp
->f_dentry
->d_inode
->i_rdev
);
662 if (info
->txbuf
!= NULL
)
665 info
->txbuf
= kmalloc (len
+ 3, GFP_KERNEL
);
666 if (info
->txbuf
== NULL
)
669 ret_val
= copy_from_user (info
->txbuf
, ubuf
, len
);
671 ret_val
= ifx_ssc_write_helper (info
, info
->txbuf
, len
, 0);
684 static struct ifx_ssc_frm_status
*
685 ifx_ssc_frm_status_get (struct ifx_ssc_port
*info
)
689 tmp
= readl(IFXMIPS_SSC_SFSTAT
);
690 info
->frm_status
.DataBusy
= (tmp
& IFX_SSC_SFSTAT_IN_DATA
) > 0;
691 info
->frm_status
.PauseBusy
= (tmp
& IFX_SSC_SFSTAT_IN_PAUSE
) > 0;
692 info
->frm_status
.DataCount
= (tmp
& IFX_SSC_SFSTAT_DATA_COUNT_MASK
) >> IFX_SSC_SFSTAT_DATA_COUNT_OFFSET
;
693 info
->frm_status
.PauseCount
= (tmp
& IFX_SSC_SFSTAT_PAUSE_COUNT_MASK
) >> IFX_SSC_SFSTAT_PAUSE_COUNT_OFFSET
;
694 tmp
= readl(IFXMIPS_SSC_SFCON
);
695 info
->frm_status
.EnIntAfterData
= (tmp
& IFX_SSC_SFCON_FIR_ENABLE_BEFORE_PAUSE
) > 0;
696 info
->frm_status
.EnIntAfterPause
= (tmp
& IFX_SSC_SFCON_FIR_ENABLE_AFTER_PAUSE
) > 0;
698 return &info
->frm_status
;
702 static struct ifx_ssc_frm_opts
*
703 ifx_ssc_frm_control_get (struct ifx_ssc_port
*info
)
707 tmp
= readl(IFXMIPS_SSC_SFCON
);
708 info
->frm_opts
.FrameEnable
= (tmp
& IFX_SSC_SFCON_SF_ENABLE
) > 0;
709 info
->frm_opts
.DataLength
= (tmp
& IFX_SSC_SFCON_DATA_LENGTH_MASK
) >> IFX_SSC_SFCON_DATA_LENGTH_OFFSET
;
710 info
->frm_opts
.PauseLength
= (tmp
& IFX_SSC_SFCON_PAUSE_LENGTH_MASK
) >> IFX_SSC_SFCON_PAUSE_LENGTH_OFFSET
;
711 info
->frm_opts
.IdleData
= (tmp
& IFX_SSC_SFCON_PAUSE_DATA_MASK
) >> IFX_SSC_SFCON_PAUSE_DATA_OFFSET
;
712 info
->frm_opts
.IdleClock
= (tmp
& IFX_SSC_SFCON_PAUSE_CLOCK_MASK
) >> IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET
;
713 info
->frm_opts
.StopAfterPause
= (tmp
& IFX_SSC_SFCON_STOP_AFTER_PAUSE
) > 0;
715 return &info
->frm_opts
;
719 ifx_ssc_frm_control_set (struct ifx_ssc_port
*info
)
724 if ((info
->frm_opts
.DataLength
> IFX_SSC_SFCON_DATA_LENGTH_MAX
)
725 || (info
->frm_opts
.DataLength
< 1)
726 || (info
->frm_opts
.PauseLength
> IFX_SSC_SFCON_PAUSE_LENGTH_MAX
)
727 || (info
->frm_opts
.PauseLength
< 1)
728 || (info
->frm_opts
.IdleData
& ~(IFX_SSC_SFCON_PAUSE_DATA_MASK
>> IFX_SSC_SFCON_PAUSE_DATA_OFFSET
))
729 || (info
->frm_opts
.IdleClock
& ~(IFX_SSC_SFCON_PAUSE_CLOCK_MASK
>> IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET
)))
732 // read interrupt bits (they're not changed here)
733 tmp
= readl(IFXMIPS_SSC_SFCON
) &
734 (IFX_SSC_SFCON_FIR_ENABLE_BEFORE_PAUSE
| IFX_SSC_SFCON_FIR_ENABLE_AFTER_PAUSE
);
736 // set all values with respect to it's bit position (for data and pause
738 tmp
= (info
->frm_opts
.DataLength
- 1) << IFX_SSC_SFCON_DATA_LENGTH_OFFSET
;
739 tmp
|= (info
->frm_opts
.PauseLength
- 1) << IFX_SSC_SFCON_PAUSE_LENGTH_OFFSET
;
740 tmp
|= info
->frm_opts
.IdleData
<< IFX_SSC_SFCON_PAUSE_DATA_OFFSET
;
741 tmp
|= info
->frm_opts
.IdleClock
<< IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET
;
742 tmp
|= info
->frm_opts
.FrameEnable
* IFX_SSC_SFCON_SF_ENABLE
;
743 tmp
|= info
->frm_opts
.StopAfterPause
* IFX_SSC_SFCON_STOP_AFTER_PAUSE
;
745 writel(tmp
, IFXMIPS_SSC_SFCON
);
751 ifx_ssc_rxtx_mode_set (struct ifx_ssc_port
*info
, unsigned int val
)
755 if (!(info
) || (val
& ~(IFX_SSC_MODE_MASK
)))
758 if ((readl(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_BUSY
)
759 || (readl(IFXMIPS_SSC_RXCNT
) & IFX_SSC_RXCNT_TODO_MASK
))
762 tmp
= (readl(IFXMIPS_SSC_CON
) & ~(IFX_SSC_CON_RX_OFF
| IFX_SSC_CON_TX_OFF
)) | (val
);
763 writel(tmp
, IFXMIPS_SSC_SFCON
);
764 info
->opts
.modeRxTx
= val
;
770 ifx_ssc_sethwopts (struct ifx_ssc_port
*info
)
772 unsigned long flags
, bits
;
773 struct ifx_ssc_hwopts
*opts
= &info
->opts
;
775 if ((opts
->dataWidth
< IFX_SSC_MIN_DATA_WIDTH
)
776 || (opts
->dataWidth
> IFX_SSC_MAX_DATA_WIDTH
))
779 bits
= (opts
->dataWidth
- 1) << IFX_SSC_CON_DATA_WIDTH_OFFSET
;
780 bits
|= IFX_SSC_CON_ENABLE_BYTE_VALID
;
782 if (opts
->rxOvErrDetect
)
783 bits
|= IFX_SSC_CON_RX_OFL_CHECK
;
784 if (opts
->rxUndErrDetect
)
785 bits
|= IFX_SSC_CON_RX_UFL_CHECK
;
786 if (opts
->txOvErrDetect
)
787 bits
|= IFX_SSC_CON_TX_OFL_CHECK
;
788 if (opts
->txUndErrDetect
)
789 bits
|= IFX_SSC_CON_TX_UFL_CHECK
;
791 bits
|= IFX_SSC_CON_LOOPBACK_MODE
;
793 bits
|= IFX_SSC_CON_ECHO_MODE_ON
;
794 if (opts
->headingControl
)
795 bits
|= IFX_SSC_CON_MSB_FIRST
;
796 if (opts
->clockPhase
)
797 bits
|= IFX_SSC_CON_LATCH_THEN_SHIFT
;
798 if (opts
->clockPolarity
)
799 bits
|= IFX_SSC_CON_CLOCK_FALL
;
801 switch (opts
->modeRxTx
)
803 case IFX_SSC_MODE_TX
:
804 bits
|= IFX_SSC_CON_RX_OFF
;
806 case IFX_SSC_MODE_RX
:
807 bits
|= IFX_SSC_CON_TX_OFF
;
811 local_irq_save (flags
);
813 writel(bits
, IFXMIPS_SSC_CON
);
814 writel((info
->opts
.gpoCs
<< IFX_SSC_GPOCON_ISCSB0_POS
) |
815 (info
->opts
.gpoInv
<< IFX_SSC_GPOCON_INVOUT0_POS
), IFXMIPS_SSC_GPOCON
);
817 writel(info
->opts
.gpoCs
<< IFX_SSC_WHBGPOSTAT_SETOUT0_POS
, IFXMIPS_SSC_WHBGPOSTAT
);
820 if (opts
->masterSelect
)
821 writel(IFX_SSC_WHBSTATE_SET_MASTER_SELECT
, IFXMIPS_SSC_WHBSTATE
);
823 writel(IFX_SSC_WHBSTATE_CLR_MASTER_SELECT
, IFXMIPS_SSC_WHBSTATE
);
825 // init serial framing
826 writel(0, IFXMIPS_SSC_SFCON
);
827 /* set up the port pins */
828 //check for general requirements to switch (external) pad/pin characteristics
829 /* TODO: P0.9 SPI_CS4, P0.10 SPI_CS5, P 0.11 SPI_CS6, because of ASC0 */
830 /* p0.15 SPI_CS1(EEPROM), P0.13 SPI_CS3, */
831 /* Set p0.15 to alternative 01, others to 00 (In/OUT) */
832 *(IFXMIPS_GPIO_P0_DIR
) = (*IFXMIPS_GPIO_P0_DIR
) | (0xA000);
833 *(IFXMIPS_GPIO_P0_ALTSEL0
) = (((*IFXMIPS_GPIO_P0_ALTSEL0
) | (0x8000)) & (~(0x2000)));
834 *(IFXMIPS_GPIO_P0_ALTSEL1
) = (((*IFXMIPS_GPIO_P0_ALTSEL1
) & (~0x8000)) & (~(0x2000)));
835 *(IFXMIPS_GPIO_P0_OD
) = (*IFXMIPS_GPIO_P0_OD
) | 0xA000;
837 /* p1.6 SPI_CS2(SFLASH), p1.0 SPI_DIN, p1.1 SPI_DOUT, p1.2 SPI_CLK */
838 *(IFXMIPS_GPIO_P1_DIR
) = ((*IFXMIPS_GPIO_P1_DIR
) | (0x46)) & (~1);
839 *(IFXMIPS_GPIO_P1_ALTSEL0
) = ((*IFXMIPS_GPIO_P1_ALTSEL0
) | (0x47));
840 *(IFXMIPS_GPIO_P1_ALTSEL1
) = (*IFXMIPS_GPIO_P1_ALTSEL1
) & (~0x47);
841 *(IFXMIPS_GPIO_P1_OD
) = (*IFXMIPS_GPIO_P1_OD
) | 0x0046;
844 /*TODO: CS4 CS5 CS6 */
845 *IFXMIPS_GPIO_P0_OUT
= ((*IFXMIPS_GPIO_P0_OUT
) | 0x2000);
847 local_irq_restore (flags
);
853 ifx_ssc_set_baud (struct ifx_ssc_port
*info
, unsigned int baud
)
855 unsigned int ifx_ssc_clock
;
861 ifx_ssc_clock
= ifx_ssc_get_kernel_clk(info
);
862 if (ifx_ssc_clock
== 0)
868 local_irq_save (flags
);
870 enabled
= (readl(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_IS_ENABLED
);
871 writel(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
873 br
= (((ifx_ssc_clock
>> 1) + baud
/ 2) / baud
) - 1;
876 if (br
> 0xffff || ((br
== 0) &&
877 ((readl(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_IS_MASTER
) == 0))) {
878 local_irq_restore (flags
);
879 printk ("%s: invalid baudrate %u\n", __func__
, baud
);
883 writel(br
, IFXMIPS_SSC_BR
);
886 writel(IFX_SSC_WHBSTATE_SET_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
888 local_irq_restore(flags
);
895 ifx_ssc_hwinit (struct ifx_ssc_port
*info
)
900 enabled
= (readl(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_IS_ENABLED
);
901 writel(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
903 if (ifx_ssc_sethwopts (info
) < 0)
905 printk ("%s: setting the hardware options failed\n", __func__
);
909 if (ifx_ssc_set_baud (info
, info
->baud
) < 0)
911 printk ("%s: setting the baud rate failed\n", __func__
);
915 local_irq_save (flags
);
918 writel((IFX_SSC_DEF_TXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_ENABLE
, IFXMIPS_SSC_TXFCON
);
920 writel((IFX_SSC_DEF_RXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_ENABLE
, IFXMIPS_SSC_RXFCON
);
922 local_irq_restore (flags
);
925 writel(IFX_SSC_WHBSTATE_SET_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
931 ifx_ssc_ioctl (struct inode
*inode
, struct file
*filp
, unsigned int cmd
, unsigned long data
)
933 struct ifx_ssc_port
*info
;
934 int line
, ret_val
= 0;
939 if ((inode
== (struct inode
*) 0) || (inode
== (struct inode
*) 1))
944 line
= MINOR (filp
->f_dentry
->d_inode
->i_rdev
);
947 if (line
< 0 || line
>= PORT_CNT
)
954 case IFX_SSC_STATS_READ
:
955 /* data must be a pointer to a struct ifx_ssc_statistics */
957 memcpy ((void *) data
, (void *) &info
->stats
,
958 sizeof (struct ifx_ssc_statistics
));
959 else if (copy_to_user ((void *) data
,
960 (void *) &info
->stats
,
961 sizeof (struct ifx_ssc_statistics
)))
964 case IFX_SSC_STATS_RESET
:
965 /* just resets the statistics counters */
966 memset ((void *) &info
->stats
, 0,
967 sizeof (struct ifx_ssc_statistics
));
969 case IFX_SSC_BAUD_SET
:
970 /* if the buffers are not empty then the port is */
971 /* busy and we shouldn't change things on-the-fly! */
972 if (!info
->txbuf
|| !info
->rxbuf
||
973 (readl(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_BUSY
)) {
979 flags
= *((unsigned long *) data
);
980 else if (copy_from_user ((void *) &flags
,
981 (void *) data
, sizeof (flags
))) {
989 if (ifx_ssc_set_baud (info
, flags
) < 0) {
995 case IFX_SSC_BAUD_GET
:
997 *((unsigned int *) data
) = info
->baud
;
998 else if (copy_to_user ((void *) data
,
999 (void *) &info
->baud
,
1000 sizeof (unsigned long)))
1003 case IFX_SSC_RXTX_MODE_SET
:
1005 tmp
= *((unsigned long *) data
);
1006 else if (copy_from_user ((void *) &tmp
,
1007 (void *) data
, sizeof (tmp
))) {
1011 ret_val
= ifx_ssc_rxtx_mode_set (info
, tmp
);
1013 case IFX_SSC_RXTX_MODE_GET
:
1014 tmp
= readl(IFXMIPS_SSC_CON
) &
1015 (~(IFX_SSC_CON_RX_OFF
| IFX_SSC_CON_TX_OFF
));
1017 *((unsigned int *) data
) = tmp
;
1018 else if (copy_to_user ((void *) data
,
1019 (void *) &tmp
, sizeof (tmp
)))
1024 ifx_ssc_abort (info
);
1027 case IFX_SSC_GPO_OUT_SET
:
1029 tmp
= *((unsigned long *) data
);
1030 else if (copy_from_user ((void *) &tmp
,
1031 (void *) data
, sizeof (tmp
))) {
1035 if (tmp
> IFX_SSC_MAX_GPO_OUT
)
1038 writel(1 << (tmp
+ IFX_SSC_WHBGPOSTAT_SETOUT0_POS
),
1039 IFXMIPS_SSC_WHBGPOSTAT
);
1041 case IFX_SSC_GPO_OUT_CLR
:
1043 tmp
= *((unsigned long *) data
);
1044 else if (copy_from_user ((void *) &tmp
, (void *) data
, sizeof (tmp
))) {
1048 if (tmp
> IFX_SSC_MAX_GPO_OUT
)
1051 writel(1 << (tmp
+ IFX_SSC_WHBGPOSTAT_CLROUT0_POS
),
1052 IFXMIPS_SSC_WHBGPOSTAT
);
1055 case IFX_SSC_GPO_OUT_GET
:
1056 tmp
= readl(IFXMIPS_SSC_GPOSTAT
);
1058 *((unsigned int *) data
) = tmp
;
1059 else if (copy_to_user ((void *) data
,
1060 (void *) &tmp
, sizeof (tmp
)))
1063 case IFX_SSC_FRM_STATUS_GET
:
1064 ifx_ssc_frm_status_get (info
);
1066 memcpy ((void *) data
, (void *) &info
->frm_status
,
1067 sizeof (struct ifx_ssc_frm_status
));
1068 else if (copy_to_user ((void *) data
,
1069 (void *) &info
->frm_status
,
1070 sizeof (struct ifx_ssc_frm_status
)))
1073 case IFX_SSC_FRM_CONTROL_GET
:
1074 ifx_ssc_frm_control_get (info
);
1076 memcpy ((void *) data
, (void *) &info
->frm_opts
,
1077 sizeof (struct ifx_ssc_frm_opts
));
1078 else if (copy_to_user ((void *) data
,
1079 (void *) &info
->frm_opts
,
1080 sizeof (struct ifx_ssc_frm_opts
)))
1083 case IFX_SSC_FRM_CONTROL_SET
:
1085 memcpy ((void *) &info
->frm_opts
, (void *) data
,
1086 sizeof (struct ifx_ssc_frm_opts
));
1087 else if (copy_to_user ((void *) &info
->frm_opts
,
1089 sizeof (struct ifx_ssc_frm_opts
))) {
1093 ret_val
= ifx_ssc_frm_control_set (info
);
1095 case IFX_SSC_HWOPTS_SET
:
1096 /* data must be a pointer to a struct ifx_ssc_hwopts */
1097 /* if the buffers are not empty then the port is */
1098 /* busy and we shouldn't change things on-the-fly! */
1099 if (!info
->txbuf
|| !info
->rxbuf
||
1100 (readl(IFXMIPS_SSC_STATE
)
1101 & IFX_SSC_STATE_BUSY
)) {
1106 memcpy ((void *) &info
->opts
, (void *) data
,
1107 sizeof (struct ifx_ssc_hwopts
));
1108 else if (copy_from_user ((void *) &info
->opts
,
1109 (void *) data
, sizeof(struct ifx_ssc_hwopts
))) {
1113 if (ifx_ssc_hwinit (info
) < 0) {
1117 case IFX_SSC_HWOPTS_GET
:
1118 /* data must be a pointer to a struct ifx_ssc_hwopts */
1120 memcpy ((void *) data
, (void *) &info
->opts
,
1121 sizeof (struct ifx_ssc_hwopts
));
1122 else if (copy_to_user ((void *) data
,
1123 (void *) &info
->opts
,
1124 sizeof (struct ifx_ssc_hwopts
)))
1128 ret_val
= -ENOIOCTLCMD
;
1133 EXPORT_SYMBOL(ifx_ssc_ioctl
);
1135 static struct file_operations ifx_ssc_fops
= {
1136 .owner
= THIS_MODULE
,
1137 .read
= ifx_ssc_read
,
1138 .write
= ifx_ssc_write
,
1139 .ioctl
= ifx_ssc_ioctl
,
1140 .open
= ifx_ssc_open
,
1141 .release
= ifx_ssc_close
,
1147 struct ifx_ssc_port
*info
;
1149 unsigned long flags
;
1153 nbytes
= PORT_CNT
* sizeof(struct ifx_ssc_port
);
1154 isp
= (struct ifx_ssc_port
*)kmalloc(nbytes
, GFP_KERNEL
);
1158 printk("%s: no memory for isp\n", __func__
);
1161 memset(isp
, 0, nbytes
);
1164 if ((i
= register_chrdev (maj
, "ssc", &ifx_ssc_fops
)) < 0)
1166 printk ("Unable to register major %d for the Infineon SSC\n", maj
);
1172 if ((i
= register_chrdev (maj
, "ssc", &ifx_ssc_fops
)) < 0)
1174 printk ("Unable to register major %d for the Infineon SSC\n", maj
);
1183 /* set default values in ifx_ssc_port */
1184 for (i
= 0; i
< PORT_CNT
; i
++) {
1187 /* default values for the HwOpts */
1188 info
->opts
.AbortErrDetect
= IFX_SSC_DEF_ABRT_ERR_DETECT
;
1189 info
->opts
.rxOvErrDetect
= IFX_SSC_DEF_RO_ERR_DETECT
;
1190 info
->opts
.rxUndErrDetect
= IFX_SSC_DEF_RU_ERR_DETECT
;
1191 info
->opts
.txOvErrDetect
= IFX_SSC_DEF_TO_ERR_DETECT
;
1192 info
->opts
.txUndErrDetect
= IFX_SSC_DEF_TU_ERR_DETECT
;
1193 info
->opts
.loopBack
= IFX_SSC_DEF_LOOP_BACK
;
1194 info
->opts
.echoMode
= IFX_SSC_DEF_ECHO_MODE
;
1195 info
->opts
.idleValue
= IFX_SSC_DEF_IDLE_DATA
;
1196 info
->opts
.clockPolarity
= IFX_SSC_DEF_CLOCK_POLARITY
;
1197 info
->opts
.clockPhase
= IFX_SSC_DEF_CLOCK_PHASE
;
1198 info
->opts
.headingControl
= IFX_SSC_DEF_HEADING_CONTROL
;
1199 info
->opts
.dataWidth
= IFX_SSC_DEF_DATA_WIDTH
;
1200 info
->opts
.modeRxTx
= IFX_SSC_DEF_MODE_RXTX
;
1201 info
->opts
.gpoCs
= IFX_SSC_DEF_GPO_CS
;
1202 info
->opts
.gpoInv
= IFX_SSC_DEF_GPO_INV
;
1203 info
->opts
.masterSelect
= IFX_SSC_DEF_MASTERSLAVE
;
1204 info
->baud
= IFX_SSC_DEF_BAUDRATE
;
1207 /* values specific to SSC1 */
1209 info
->mapbase
= IFXMIPS_SSC_BASE_ADDR
;
1212 writel(IFX_SSC_DEF_RMC
<< IFX_CLC_RUN_DIVIDER_OFFSET
, IFXMIPS_SSC_CLC
);
1214 init_waitqueue_head (&info
->rwait
);
1216 local_irq_save (flags
);
1218 // init serial framing register
1219 writel(IFX_SSC_DEF_SFCON
, IFXMIPS_SSC_SFCON
);
1221 ret_val
= request_irq(IFXMIPS_SSC_TIR
, ifx_ssc_tx_int
, IRQF_DISABLED
, "ifx_ssc_tx", info
);
1224 printk("%s: unable to get irq %d\n", __func__
, IFXMIPS_SSC_TIR
);
1225 local_irq_restore(flags
);
1229 ret_val
= request_irq(IFXMIPS_SSC_RIR
, ifx_ssc_rx_int
, IRQF_DISABLED
, "ifx_ssc_rx", info
);
1232 printk ("%s: unable to get irq %d\n", __func__
, IFXMIPS_SSC_RIR
);
1233 local_irq_restore (flags
);
1237 ret_val
= request_irq(IFXMIPS_SSC_EIR
, ifx_ssc_err_int
, IRQF_DISABLED
, "ifx_ssc_err", info
);
1240 printk ("%s: unable to get irq %d\n", __func__
, IFXMIPS_SSC_EIR
);
1241 local_irq_restore (flags
);
1244 writel(IFX_SSC_DEF_IRNEN
, IFXMIPS_SSC_IRN
);
1246 //enable_irq(IFXMIPS_SSC_TIR);
1247 //enable_irq(IFXMIPS_SSC_RIR);
1248 //enable_irq(IFXMIPS_SSC_EIR);
1250 local_irq_restore (flags
);
1253 for (i
= 0; i
< PORT_CNT
; i
++) {
1255 if (ifx_ssc_hwinit (info
) < 0)
1257 printk ("%s: hardware init failed for port %d\n", __func__
, i
);
1266 free_irq(IFXMIPS_SSC_TIR
, &isp
[0]);
1267 free_irq(IFXMIPS_SSC_RIR
, &isp
[0]);
1268 free_irq(IFXMIPS_SSC_EIR
, &isp
[0]);
1275 ifx_ssc_cleanup_module (void)
1279 for (i
= 0; i
< PORT_CNT
; i
++) {
1280 writel(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
1281 free_irq(IFXMIPS_SSC_TIR
, &isp
[i
]);
1282 free_irq(IFXMIPS_SSC_RIR
, &isp
[i
]);
1283 free_irq(IFXMIPS_SSC_EIR
, &isp
[i
]);
1288 module_init(ifx_ssc_init
);
1289 module_exit(ifx_ssc_cleanup_module
);
1293 ifx_ssc_cs_low (u32 pin
)
1296 if ((ret
= ifx_ssc_ioctl ((struct inode
*) 0, NULL
, IFX_SSC_GPO_OUT_CLR
, (unsigned long) &pin
)))
1297 printk ("clear CS %d fails\n", pin
);
1302 EXPORT_SYMBOL(ifx_ssc_cs_low
);
1305 ifx_ssc_cs_high (u32 pin
)
1308 if ((ret
= ifx_ssc_ioctl((struct inode
*) 0, NULL
, IFX_SSC_GPO_OUT_SET
, (unsigned long) &pin
)))
1309 printk ("set CS %d fails\n", pin
);
1314 EXPORT_SYMBOL(ifx_ssc_cs_high
);
1317 ssc_session (char *tx_buf
, u32 tx_len
, char *rx_buf
, u32 rx_len
)
1321 char *ssc_tx_buf
= NULL
;
1322 char *ssc_rx_buf
= NULL
;
1326 if (tx_buf
== NULL
&& tx_len
== 0 && rx_buf
== NULL
&& rx_len
== 0) {
1327 printk ("invalid parameters\n");
1329 goto ssc_session_exit
;
1331 else if (tx_buf
== NULL
|| tx_len
== 0) {
1332 if (rx_buf
!= NULL
&& rx_len
!= 0) {
1333 mode
= IFX_SSC_MODE_RX
;
1336 printk ("invalid parameters\n");
1338 goto ssc_session_exit
;
1341 else if (rx_buf
== NULL
|| rx_len
== 0) {
1342 if (tx_buf
!= NULL
&& tx_len
!= 0) {
1343 mode
= IFX_SSC_MODE_TX
;
1346 printk ("invalid parameters\n");
1348 goto ssc_session_exit
;
1352 mode
= IFX_SSC_MODE_RXTX
;
1355 if (mode
== IFX_SSC_MODE_RXTX
) {
1356 eff_size
= tx_len
+ rx_len
;
1358 else if (mode
== IFX_SSC_MODE_RX
) {
1365 //4 bytes alignment, required by driver
1366 /* change by TaiCheng */
1370 (char *) kmalloc (sizeof (char) *
1371 ((eff_size
+ 3) & (~3)),
1374 (char *) kmalloc (sizeof (char) *
1375 ((eff_size
+ 3) & (~3)),
1380 (char *) kmalloc (sizeof (char) *
1381 ((eff_size
+ 3) & (~3)),
1384 (char *) kmalloc (sizeof (char) *
1385 ((eff_size
+ 3) & (~3)),
1388 if (ssc_tx_buf
== NULL
|| ssc_rx_buf
== NULL
) {
1389 printk ("no memory for size of %d\n", eff_size
);
1391 goto ssc_session_exit
;
1393 memset ((void *) ssc_tx_buf
, 0, eff_size
);
1394 memset ((void *) ssc_rx_buf
, 0, eff_size
);
1397 memcpy (ssc_tx_buf
, tx_buf
, tx_len
);
1400 ret
= ifx_ssc_kwrite (0, ssc_tx_buf
, eff_size
);
1403 ssc_tx_buf
= NULL
; //should be freed by ifx_ssc_kwrite
1406 if (ret
!= eff_size
) {
1407 printk ("ifx_ssc_write return %d\n", ret
);
1408 goto ssc_session_exit
;
1410 ret
= ifx_ssc_kread (0, ssc_rx_buf
, eff_size
);
1411 if (ret
!= eff_size
) {
1412 printk ("ifx_ssc_read return %d\n", ret
);
1413 goto ssc_session_exit
;
1416 memcpy (rx_buf
, ssc_rx_buf
+ tx_len
, rx_len
);
1418 if (mode
== IFX_SSC_MODE_TX
) {
1426 if (ssc_tx_buf
!= NULL
)
1428 if (ssc_rx_buf
!= NULL
)
1432 printk ("ssc session fails\n");
1438 ifx_ssc_txrx (char *tx_buf
, u32 tx_len
, char *rx_buf
, u32 rx_len
)
1440 return ssc_session(tx_buf
, tx_len
, rx_buf
, rx_len
);
1442 EXPORT_SYMBOL(ifx_ssc_txrx
);
1445 ifx_ssc_tx (char *tx_buf
, u32 tx_len
)
1447 return ssc_session(tx_buf
, tx_len
, NULL
, 0);
1449 EXPORT_SYMBOL(ifx_ssc_tx
);
1452 ifx_ssc_rx (char *rx_buf
, u32 rx_len
)
1454 return ssc_session(NULL
, 0, rx_buf
, rx_len
);
1456 EXPORT_SYMBOL(ifx_ssc_rx
);
1458 MODULE_LICENSE("GPL");
1459 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
1460 MODULE_DESCRIPTION("ifxmips ssc driver");