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>
22 ### TO DO: general issues:
24 - interrupt handling (direct/indirect)
25 - pin/mux-handling (just overall concept due to project dependency)
26 - multiple instances capability
30 #include <linux/module.h>
31 #include <linux/errno.h>
32 #include <linux/signal.h>
33 #include <linux/sched.h>
34 #include <linux/timer.h>
35 #include <linux/interrupt.h>
36 #include <linux/major.h>
37 #include <linux/string.h>
39 #include <linux/fcntl.h>
40 #include <linux/ptrace.h>
42 #include <linux/ioport.h>
43 #include <linux/init.h>
44 #include <linux/delay.h>
45 #include <linux/spinlock.h>
46 #include <linux/slab.h>
48 #include <linux/irq.h>
49 #include <linux/uaccess.h>
50 #include <linux/bitops.h>
52 #include <linux/types.h>
53 #include <linux/kernel.h>
54 #include <linux/version.h>
56 #include <asm/system.h>
57 #include <asm/ifxmips/ifxmips.h>
58 #include <asm/ifxmips/ifxmips_irq.h>
59 #include <asm/ifxmips/ifx_ssc_defines.h>
60 #include <asm/ifxmips/ifx_ssc.h>
62 /* allow the user to set the major device number */
66 * This is the per-channel data structure containing pointers, flags
67 * and variables for the port. This driver supports a maximum of PORT_CNT.
68 * isp is allocated in ifx_ssc_init() based on the chip version.
70 static struct ifx_ssc_port
*isp
;
72 /* other forward declarations */
73 static unsigned int ifx_ssc_get_kernel_clk(struct ifx_ssc_port
*info
);
74 static void tx_int(struct ifx_ssc_port
*);
76 extern unsigned int ifxmips_get_fpi_hz(void);
77 extern void ifxmips_mask_and_ack_irq(unsigned int irq_nr
);
79 static inline unsigned int ifx_ssc_get_kernel_clk(struct ifx_ssc_port
*info
)
83 rmc
= (ifxmips_r32(IFXMIPS_SSC_CLC
) & IFX_CLC_RUN_DIVIDER_MASK
) >> IFX_CLC_RUN_DIVIDER_OFFSET
;
85 printk("ifx_ssc_get_kernel_clk rmc==0 \n");
88 return ifxmips_get_fpi_hz() / rmc
;
91 static inline void rx_int(struct ifx_ssc_port
*info
)
93 int fifo_fill_lev
, bytes_in_buf
, i
;
94 unsigned long tmp_val
;
95 unsigned long *tmp_ptr
;
96 unsigned int rx_valid_cnt
;
97 /* number of words waiting in the RX FIFO */
98 fifo_fill_lev
= (ifxmips_r32(IFXMIPS_SSC_FSTAT
) & IFX_SSC_FSTAT_RECEIVED_WORDS_MASK
) >> IFX_SSC_FSTAT_RECEIVED_WORDS_OFFSET
;
99 bytes_in_buf
= info
->rxbuf_end
- info
->rxbuf_ptr
;
100 /* transfer with 32 bits per entry */
101 while ((bytes_in_buf
>= 4) && (fifo_fill_lev
> 0)) {
102 tmp_ptr
= (unsigned long *)info
->rxbuf_ptr
;
103 *tmp_ptr
= ifxmips_r32(IFXMIPS_SSC_RB
);
104 info
->rxbuf_ptr
+= 4;
105 info
->stats
.rxBytes
+= 4;
110 /* now do the rest as mentioned in STATE.RXBV */
111 while ((bytes_in_buf
> 0) && (fifo_fill_lev
> 0)) {
112 rx_valid_cnt
= (ifxmips_r32(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_RX_BYTE_VALID_MASK
) >> IFX_SSC_STATE_RX_BYTE_VALID_OFFSET
;
113 if (rx_valid_cnt
== 0)
116 if (rx_valid_cnt
> bytes_in_buf
)
117 rx_valid_cnt
= bytes_in_buf
;
119 tmp_val
= ifxmips_r32(IFXMIPS_SSC_RB
);
121 for (i
= 0; i
< rx_valid_cnt
; i
++) {
122 *info
->rxbuf_ptr
= (tmp_val
>> (8 * (rx_valid_cnt
- i
- 1))) & 0xff;
126 info
->stats
.rxBytes
+= rx_valid_cnt
;
129 /* check if transfer is complete */
130 if (info
->rxbuf_ptr
>= info
->rxbuf_end
) {
131 disable_irq(IFXMIPS_SSC_RIR
);
132 wake_up_interruptible(&info
->rwait
);
133 } else if ((info
->opts
.modeRxTx
== IFX_SSC_MODE_RX
) && (ifxmips_r32(IFXMIPS_SSC_RXCNT
) == 0)) {
134 if (info
->rxbuf_end
- info
->rxbuf_ptr
< IFX_SSC_RXREQ_BLOCK_SIZE
)
135 ifxmips_w32((info
->rxbuf_end
- info
->rxbuf_ptr
) << IFX_SSC_RXREQ_RXCOUNT_OFFSET
, IFXMIPS_SSC_RXREQ
);
137 ifxmips_w32(IFX_SSC_RXREQ_BLOCK_SIZE
<< IFX_SSC_RXREQ_RXCOUNT_OFFSET
, IFXMIPS_SSC_RXREQ
);
141 static inline void tx_int(struct ifx_ssc_port
*info
)
144 int fifo_space
, fill
, i
;
145 fifo_space
= ((ifxmips_r32(IFXMIPS_SSC_ID
) & IFX_SSC_PERID_TXFS_MASK
) >> IFX_SSC_PERID_TXFS_OFFSET
)
146 -((ifxmips_r32(IFXMIPS_SSC_FSTAT
) & IFX_SSC_FSTAT_TRANSMIT_WORDS_MASK
) >> IFX_SSC_FSTAT_TRANSMIT_WORDS_OFFSET
);
151 fill
= info
->txbuf_end
- info
->txbuf_ptr
;
153 if (fill
> fifo_space
* 4)
154 fill
= fifo_space
* 4;
156 for (i
= 0; i
< fill
/ 4; i
++) {
157 /* at first 32 bit access */
158 ifxmips_w32(*(UINT32
*)info
->txbuf_ptr
, IFXMIPS_SSC_TB
);
159 info
->txbuf_ptr
+= 4;
162 fifo_space
-= fill
/ 4;
163 info
->stats
.txBytes
+= fill
& ~0x3;
165 if ((fifo_space
> 0) & (fill
> 1)) {
166 /* trailing 16 bit access */
167 WRITE_PERIPHERAL_REGISTER_16(*(UINT16
*)info
->txbuf_ptr
, info
->mapbase
+ IFX_SSC_TB
);
168 info
->txbuf_ptr
+= 2;
169 info
->stats
.txBytes
+= 2;
174 if ((fifo_space
> 0) & (fill
> 0)) {
175 /* trailing 8 bit access */
176 WRITE_PERIPHERAL_REGISTER_8(*(UINT8
*)info
->txbuf_ptr
, info
->mapbase
+ IFX_SSC_TB
);
178 info
->stats
.txBytes
++;
181 /* check if transmission complete */
182 if (info
->txbuf_ptr
>= info
->txbuf_end
) {
183 disable_irq(IFXMIPS_SSC_TIR
);
190 irqreturn_t
ifx_ssc_rx_int(int irq
, void *dev_id
)
192 struct ifx_ssc_port
*info
= (struct ifx_ssc_port
*)dev_id
;
198 irqreturn_t
ifx_ssc_tx_int(int irq
, void *dev_id
)
200 struct ifx_ssc_port
*info
= (struct ifx_ssc_port
*)dev_id
;
206 irqreturn_t
ifx_ssc_err_int(int irq
, void *dev_id
)
208 struct ifx_ssc_port
*info
= (struct ifx_ssc_port
*)dev_id
;
210 unsigned int write_back
= 0;
213 local_irq_save(flags
);
214 state
= ifxmips_r32(IFXMIPS_SSC_STATE
);
216 if ((state
& IFX_SSC_STATE_RX_UFL
) != 0) {
217 info
->stats
.rxUnErr
++;
218 write_back
|= IFX_SSC_WHBSTATE_CLR_RX_UFL_ERROR
;
221 if ((state
& IFX_SSC_STATE_RX_OFL
) != 0) {
222 info
->stats
.rxOvErr
++;
223 write_back
|= IFX_SSC_WHBSTATE_CLR_RX_OFL_ERROR
;
226 if ((state
& IFX_SSC_STATE_TX_OFL
) != 0) {
227 info
->stats
.txOvErr
++;
228 write_back
|= IFX_SSC_WHBSTATE_CLR_TX_OFL_ERROR
;
231 if ((state
& IFX_SSC_STATE_TX_UFL
) != 0) {
232 info
->stats
.txUnErr
++;
233 write_back
|= IFX_SSC_WHBSTATE_CLR_TX_UFL_ERROR
;
236 if ((state
& IFX_SSC_STATE_MODE_ERR
) != 0) {
237 info
->stats
.modeErr
++;
238 write_back
|= IFX_SSC_WHBSTATE_CLR_MODE_ERROR
;
242 ifxmips_w32(write_back
, IFXMIPS_SSC_WHBSTATE
);
244 local_irq_restore(flags
);
249 static void ifx_ssc_abort(struct ifx_ssc_port
*info
)
254 local_irq_save(flags
);
256 disable_irq(IFXMIPS_SSC_RIR
);
257 disable_irq(IFXMIPS_SSC_TIR
);
258 disable_irq(IFXMIPS_SSC_EIR
);
260 local_irq_restore(flags
);
262 /* disable SSC(also aborts a receive request!) */
263 /* ### TO DO: Perhaps it's better to abort after the receiption of a
264 complete word. The disable cuts the transmission immediatly and
265 releases the chip selects. This could result in unpredictable
266 behavior of connected external devices!
268 enabled
= (ifxmips_r32(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_IS_ENABLED
) != 0;
269 ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
272 ifxmips_w32(IFX_SSC_XFCON_FIFO_FLUSH
, IFXMIPS_SSC_TXFCON
);
273 ifxmips_w32(IFX_SSC_XFCON_FIFO_FLUSH
, IFXMIPS_SSC_RXFCON
);
276 if (info
->txbuf
!= NULL
) {
281 /* wakeup read process */
282 if (info
->rxbuf
!= NULL
)
283 wake_up_interruptible(&info
->rwait
);
285 /* clear pending int's */
286 ifxmips_mask_and_ack_irq(IFXMIPS_SSC_RIR
);
287 ifxmips_mask_and_ack_irq(IFXMIPS_SSC_TIR
);
288 ifxmips_mask_and_ack_irq(IFXMIPS_SSC_EIR
);
290 /* clear error flags */
291 ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ALL_ERROR
, IFXMIPS_SSC_WHBSTATE
);
294 ifxmips_w32(IFX_SSC_WHBSTATE_SET_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
299 * This routine is called whenever a port is opened. It enforces
300 * exclusive opening of a port and enables interrupts, etc.
302 int ifx_ssc_open(struct inode
*inode
, struct file
*filp
)
304 struct ifx_ssc_port
*info
;
308 if ((inode
== (struct inode
*)0) || (inode
== (struct inode
*)1)) {
312 line
= MINOR(filp
->f_dentry
->d_inode
->i_rdev
);
314 /* don't open more minor devices than we can support */
315 if (line
< 0 || line
>= PORT_CNT
)
321 if (info
->port_is_open
!= 0)
323 info
->port_is_open
++;
325 disable_irq(IFXMIPS_SSC_RIR
);
326 disable_irq(IFXMIPS_SSC_TIR
);
327 disable_irq(IFXMIPS_SSC_EIR
);
329 /* Flush and enable TX/RX FIFO */
330 ifxmips_w32((IFX_SSC_DEF_TXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_FLUSH
| IFX_SSC_XFCON_FIFO_ENABLE
, IFXMIPS_SSC_TXFCON
);
331 ifxmips_w32((IFX_SSC_DEF_RXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_FLUSH
| IFX_SSC_XFCON_FIFO_ENABLE
, IFXMIPS_SSC_RXFCON
);
333 /* logically flush the software FIFOs */
337 /* clear all error bits */
338 ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ALL_ERROR
, IFXMIPS_SSC_WHBSTATE
);
340 /* clear pending interrupts */
341 ifxmips_mask_and_ack_irq(IFXMIPS_SSC_RIR
);
342 ifxmips_mask_and_ack_irq(IFXMIPS_SSC_TIR
);
343 ifxmips_mask_and_ack_irq(IFXMIPS_SSC_EIR
);
345 ifxmips_w32(IFX_SSC_WHBSTATE_SET_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
349 EXPORT_SYMBOL(ifx_ssc_open
);
351 int ifx_ssc_close(struct inode
*inode
, struct file
*filp
)
353 struct ifx_ssc_port
*info
;
356 if ((inode
== (struct inode
*)0) || (inode
== (struct inode
*)1))
359 idx
= MINOR(filp
->f_dentry
->d_inode
->i_rdev
);
361 if (idx
< 0 || idx
>= PORT_CNT
)
368 ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
372 info
->port_is_open
--;
376 EXPORT_SYMBOL(ifx_ssc_close
);
378 static ssize_t
ifx_ssc_read_helper_poll(struct ifx_ssc_port
*info
, char *buf
,
379 size_t len
, int from_kernel
)
384 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_TX
)
386 local_irq_save(flags
);
387 info
->rxbuf_ptr
= info
->rxbuf
;
388 info
->rxbuf_end
= info
->rxbuf
+ len
;
389 local_irq_restore(flags
);
390 /* Vinetic driver always works in IFX_SSC_MODE_RXTX */
391 /* TXRX in poll mode */
392 while (info
->rxbuf_ptr
< info
->rxbuf_end
) {
393 if (info
->txbuf_ptr
< info
->txbuf_end
)
399 ret_val
= info
->rxbuf_ptr
- info
->rxbuf
;
404 static ssize_t
ifx_ssc_read_helper(struct ifx_ssc_port
*info
, char *buf
,
405 size_t len
, int from_kernel
)
409 DECLARE_WAITQUEUE(wait
, current
);
411 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_TX
)
414 local_irq_save(flags
);
415 info
->rxbuf_ptr
= info
->rxbuf
;
416 info
->rxbuf_end
= info
->rxbuf
+ len
;
418 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_RXTX
) {
419 if ((info
->txbuf
== NULL
) || (info
->txbuf
!= info
->txbuf_ptr
) || (info
->txbuf_end
!= len
+ info
->txbuf
)) {
420 local_irq_restore(flags
);
421 printk("IFX SSC - %s: write must be called before calling " "read in combined RX/TX!\n", __func__
);
425 local_irq_restore(flags
);
428 if (info
->txbuf_ptr
< info
->txbuf_end
)
429 enable_irq(IFXMIPS_SSC_TIR
);
431 enable_irq(IFXMIPS_SSC_RIR
);
433 local_irq_restore(flags
);
434 if (ifxmips_r32(IFXMIPS_SSC_RXCNT
) & IFX_SSC_RXCNT_TODO_MASK
)
436 enable_irq(IFXMIPS_SSC_RIR
);
437 if (len
< IFX_SSC_RXREQ_BLOCK_SIZE
)
438 ifxmips_w32(len
<< IFX_SSC_RXREQ_RXCOUNT_OFFSET
, IFXMIPS_SSC_RXREQ
);
440 ifxmips_w32(IFX_SSC_RXREQ_BLOCK_SIZE
<< IFX_SSC_RXREQ_RXCOUNT_OFFSET
, IFXMIPS_SSC_RXREQ
);
443 __add_wait_queue(&info
->rwait
, &wait
);
444 set_current_state(TASK_INTERRUPTIBLE
);
447 local_irq_save(flags
);
448 if (info
->rxbuf_ptr
>= info
->rxbuf_end
)
451 local_irq_restore(flags
);
453 if (signal_pending(current
)) {
454 ret_val
= -ERESTARTSYS
;
460 ret_val
= info
->rxbuf_ptr
- info
->rxbuf
;
461 local_irq_restore(flags
);
464 current
->state
= TASK_RUNNING
;
465 __remove_wait_queue(&info
->rwait
, &wait
);
470 static ssize_t
ifx_ssc_write_helper(struct ifx_ssc_port
*info
, const char *buf
,
471 size_t len
, int from_kernel
)
473 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_RX
)
476 info
->txbuf_ptr
= info
->txbuf
;
477 info
->txbuf_end
= len
+ info
->txbuf
;
478 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_TX
) {
480 if (info
->txbuf_ptr
< info
->txbuf_end
)
481 enable_irq(IFXMIPS_SSC_TIR
);
487 ssize_t
ifx_ssc_kread(int port
, char *kbuf
, size_t len
)
489 struct ifx_ssc_port
*info
;
492 if (port
< 0 || port
>= PORT_CNT
)
500 if (info
->rxbuf
!= NULL
) {
501 printk("SSC device busy\n");
506 if (info
->rxbuf
== NULL
) {
507 printk("SSC device error\n");
511 ret_val
= ifx_ssc_read_helper_poll(info
, kbuf
, len
, 1);
514 disable_irq(IFXMIPS_SSC_RIR
);
518 EXPORT_SYMBOL(ifx_ssc_kread
);
520 ssize_t
ifx_ssc_kwrite(int port
, const char *kbuf
, size_t len
)
522 struct ifx_ssc_port
*info
;
525 if (port
< 0 || port
>= PORT_CNT
)
533 /* check if transmission in progress */
534 if (info
->txbuf
!= NULL
)
537 info
->txbuf
= (char *)kbuf
;
539 ret_val
= ifx_ssc_write_helper(info
, info
->txbuf
, len
, 1);
546 EXPORT_SYMBOL(ifx_ssc_kwrite
);
548 static ssize_t
ifx_ssc_read(struct file
*filp
, char *ubuf
, size_t len
, loff_t
*off
)
552 struct ifx_ssc_port
*info
;
554 idx
= MINOR(filp
->f_dentry
->d_inode
->i_rdev
);
557 if (info
->rxbuf
!= NULL
)
560 info
->rxbuf
= kmalloc(len
+ 3, GFP_KERNEL
);
561 if (info
->rxbuf
== NULL
)
564 ret_val
= ifx_ssc_read_helper(info
, info
->rxbuf
, len
, 0);
565 if (copy_to_user((void *)ubuf
, info
->rxbuf
, ret_val
) != 0)
568 disable_irq(IFXMIPS_SSC_RIR
);
576 static ssize_t
ifx_ssc_write(struct file
*filp
, const char *ubuf
, size_t len
, loff_t
*off
)
579 struct ifx_ssc_port
*info
;
585 idx
= MINOR(filp
->f_dentry
->d_inode
->i_rdev
);
588 if (info
->txbuf
!= NULL
)
591 info
->txbuf
= kmalloc(len
+ 3, GFP_KERNEL
);
592 if (info
->txbuf
== NULL
)
595 ret_val
= copy_from_user(info
->txbuf
, ubuf
, len
);
597 ret_val
= ifx_ssc_write_helper(info
, info
->txbuf
, len
, 0);
609 static struct ifx_ssc_frm_status
*ifx_ssc_frm_status_get(struct ifx_ssc_port
*info
)
613 tmp
= ifxmips_r32(IFXMIPS_SSC_SFSTAT
);
614 info
->frm_status
.DataBusy
= (tmp
& IFX_SSC_SFSTAT_IN_DATA
) > 0;
615 info
->frm_status
.PauseBusy
= (tmp
& IFX_SSC_SFSTAT_IN_PAUSE
) > 0;
616 info
->frm_status
.DataCount
= (tmp
& IFX_SSC_SFSTAT_DATA_COUNT_MASK
) >> IFX_SSC_SFSTAT_DATA_COUNT_OFFSET
;
617 info
->frm_status
.PauseCount
= (tmp
& IFX_SSC_SFSTAT_PAUSE_COUNT_MASK
) >> IFX_SSC_SFSTAT_PAUSE_COUNT_OFFSET
;
618 tmp
= ifxmips_r32(IFXMIPS_SSC_SFCON
);
619 info
->frm_status
.EnIntAfterData
= (tmp
& IFX_SSC_SFCON_FIR_ENABLE_BEFORE_PAUSE
) > 0;
620 info
->frm_status
.EnIntAfterPause
= (tmp
& IFX_SSC_SFCON_FIR_ENABLE_AFTER_PAUSE
) > 0;
622 return &info
->frm_status
;
625 static struct ifx_ssc_frm_opts
*ifx_ssc_frm_control_get(struct ifx_ssc_port
*info
)
629 tmp
= ifxmips_r32(IFXMIPS_SSC_SFCON
);
630 info
->frm_opts
.FrameEnable
= (tmp
& IFX_SSC_SFCON_SF_ENABLE
) > 0;
631 info
->frm_opts
.DataLength
= (tmp
& IFX_SSC_SFCON_DATA_LENGTH_MASK
) >> IFX_SSC_SFCON_DATA_LENGTH_OFFSET
;
632 info
->frm_opts
.PauseLength
= (tmp
& IFX_SSC_SFCON_PAUSE_LENGTH_MASK
) >> IFX_SSC_SFCON_PAUSE_LENGTH_OFFSET
;
633 info
->frm_opts
.IdleData
= (tmp
& IFX_SSC_SFCON_PAUSE_DATA_MASK
) >> IFX_SSC_SFCON_PAUSE_DATA_OFFSET
;
634 info
->frm_opts
.IdleClock
= (tmp
& IFX_SSC_SFCON_PAUSE_CLOCK_MASK
) >> IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET
;
635 info
->frm_opts
.StopAfterPause
= (tmp
& IFX_SSC_SFCON_STOP_AFTER_PAUSE
) > 0;
637 return &info
->frm_opts
;
640 static int ifx_ssc_frm_control_set(struct ifx_ssc_port
*info
)
644 if ((info
->frm_opts
.DataLength
> IFX_SSC_SFCON_DATA_LENGTH_MAX
)
645 || (info
->frm_opts
.DataLength
< 1)
646 || (info
->frm_opts
.PauseLength
> IFX_SSC_SFCON_PAUSE_LENGTH_MAX
)
647 || (info
->frm_opts
.PauseLength
< 1)
648 || (info
->frm_opts
.IdleData
& ~(IFX_SSC_SFCON_PAUSE_DATA_MASK
>> IFX_SSC_SFCON_PAUSE_DATA_OFFSET
))
649 || (info
->frm_opts
.IdleClock
& ~(IFX_SSC_SFCON_PAUSE_CLOCK_MASK
>> IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET
)))
652 /* read interrupt bits(they're not changed here) */
653 tmp
= ifxmips_r32(IFXMIPS_SSC_SFCON
) &
654 (IFX_SSC_SFCON_FIR_ENABLE_BEFORE_PAUSE
| IFX_SSC_SFCON_FIR_ENABLE_AFTER_PAUSE
);
656 /* set all values with respect to it's bit position(for data and pause
658 tmp
= (info
->frm_opts
.DataLength
- 1) << IFX_SSC_SFCON_DATA_LENGTH_OFFSET
;
659 tmp
|= (info
->frm_opts
.PauseLength
- 1) << IFX_SSC_SFCON_PAUSE_LENGTH_OFFSET
;
660 tmp
|= info
->frm_opts
.IdleData
<< IFX_SSC_SFCON_PAUSE_DATA_OFFSET
;
661 tmp
|= info
->frm_opts
.IdleClock
<< IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET
;
662 tmp
|= info
->frm_opts
.FrameEnable
* IFX_SSC_SFCON_SF_ENABLE
;
663 tmp
|= info
->frm_opts
.StopAfterPause
* IFX_SSC_SFCON_STOP_AFTER_PAUSE
;
665 ifxmips_w32(tmp
, IFXMIPS_SSC_SFCON
);
670 static int ifx_ssc_rxtx_mode_set(struct ifx_ssc_port
*info
, unsigned int val
)
674 if (!(info
) || (val
& ~(IFX_SSC_MODE_MASK
)))
677 if ((ifxmips_r32(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_BUSY
)
678 || (ifxmips_r32(IFXMIPS_SSC_RXCNT
) & IFX_SSC_RXCNT_TODO_MASK
))
681 tmp
= (ifxmips_r32(IFXMIPS_SSC_CON
) & ~(IFX_SSC_CON_RX_OFF
| IFX_SSC_CON_TX_OFF
)) | (val
);
682 ifxmips_w32(tmp
, IFXMIPS_SSC_SFCON
);
683 info
->opts
.modeRxTx
= val
;
688 static int ifx_ssc_sethwopts(struct ifx_ssc_port
*info
)
690 unsigned long flags
, bits
;
691 struct ifx_ssc_hwopts
*opts
= &info
->opts
;
693 if ((opts
->dataWidth
< IFX_SSC_MIN_DATA_WIDTH
)
694 || (opts
->dataWidth
> IFX_SSC_MAX_DATA_WIDTH
))
697 bits
= (opts
->dataWidth
- 1) << IFX_SSC_CON_DATA_WIDTH_OFFSET
;
698 bits
|= IFX_SSC_CON_ENABLE_BYTE_VALID
;
700 if (opts
->rxOvErrDetect
)
701 bits
|= IFX_SSC_CON_RX_OFL_CHECK
;
702 if (opts
->rxUndErrDetect
)
703 bits
|= IFX_SSC_CON_RX_UFL_CHECK
;
704 if (opts
->txOvErrDetect
)
705 bits
|= IFX_SSC_CON_TX_OFL_CHECK
;
706 if (opts
->txUndErrDetect
)
707 bits
|= IFX_SSC_CON_TX_UFL_CHECK
;
709 bits
|= IFX_SSC_CON_LOOPBACK_MODE
;
711 bits
|= IFX_SSC_CON_ECHO_MODE_ON
;
712 if (opts
->headingControl
)
713 bits
|= IFX_SSC_CON_MSB_FIRST
;
714 if (opts
->clockPhase
)
715 bits
|= IFX_SSC_CON_LATCH_THEN_SHIFT
;
716 if (opts
->clockPolarity
)
717 bits
|= IFX_SSC_CON_CLOCK_FALL
;
719 switch (opts
->modeRxTx
) {
720 case IFX_SSC_MODE_TX
:
721 bits
|= IFX_SSC_CON_RX_OFF
;
723 case IFX_SSC_MODE_RX
:
724 bits
|= IFX_SSC_CON_TX_OFF
;
728 local_irq_save(flags
);
730 ifxmips_w32(bits
, IFXMIPS_SSC_CON
);
731 ifxmips_w32((info
->opts
.gpoCs
<< IFX_SSC_GPOCON_ISCSB0_POS
) |
732 (info
->opts
.gpoInv
<< IFX_SSC_GPOCON_INVOUT0_POS
), IFXMIPS_SSC_GPOCON
);
734 ifxmips_w32(info
->opts
.gpoCs
<< IFX_SSC_WHBGPOSTAT_SETOUT0_POS
, IFXMIPS_SSC_WHBGPOSTAT
);
737 if (opts
->masterSelect
)
738 ifxmips_w32(IFX_SSC_WHBSTATE_SET_MASTER_SELECT
, IFXMIPS_SSC_WHBSTATE
);
740 ifxmips_w32(IFX_SSC_WHBSTATE_CLR_MASTER_SELECT
, IFXMIPS_SSC_WHBSTATE
);
742 /* init serial framing */
743 ifxmips_w32(0, IFXMIPS_SSC_SFCON
);
744 /* set up the port pins */
745 /* check for general requirements to switch(external) pad/pin characteristics */
746 /* TODO: P0.9 SPI_CS4, P0.10 SPI_CS5, P 0.11 SPI_CS6, because of ASC0 */
747 /* p0.15 SPI_CS1(EEPROM), P0.13 SPI_CS3, */
748 /* Set p0.15 to alternative 01, others to 00(In/OUT) */
749 *(IFXMIPS_GPIO_P0_DIR
) = (*IFXMIPS_GPIO_P0_DIR
) | (0xA000);
750 *(IFXMIPS_GPIO_P0_ALTSEL0
) = (((*IFXMIPS_GPIO_P0_ALTSEL0
) | (0x8000)) & (~(0x2000)));
751 *(IFXMIPS_GPIO_P0_ALTSEL1
) = (((*IFXMIPS_GPIO_P0_ALTSEL1
) & (~0x8000)) & (~(0x2000)));
752 *(IFXMIPS_GPIO_P0_OD
) = (*IFXMIPS_GPIO_P0_OD
) | 0xA000;
754 /* p1.6 SPI_CS2(SFLASH), p1.0 SPI_DIN, p1.1 SPI_DOUT, p1.2 SPI_CLK */
755 *(IFXMIPS_GPIO_P1_DIR
) = ((*IFXMIPS_GPIO_P1_DIR
) | (0x46)) & (~1);
756 *(IFXMIPS_GPIO_P1_ALTSEL0
) = ((*IFXMIPS_GPIO_P1_ALTSEL0
) | (0x47));
757 *(IFXMIPS_GPIO_P1_ALTSEL1
) = (*IFXMIPS_GPIO_P1_ALTSEL1
) & (~0x47);
758 *(IFXMIPS_GPIO_P1_OD
) = (*IFXMIPS_GPIO_P1_OD
) | 0x0046;
761 /*TODO: CS4 CS5 CS6 */
762 *IFXMIPS_GPIO_P0_OUT
= ((*IFXMIPS_GPIO_P0_OUT
) | 0x2000);
764 local_irq_restore(flags
);
769 static int ifx_ssc_set_baud(struct ifx_ssc_port
*info
, unsigned int baud
)
771 unsigned int ifx_ssc_clock
;
777 ifx_ssc_clock
= ifx_ssc_get_kernel_clk(info
);
778 if (ifx_ssc_clock
== 0) {
783 local_irq_save(flags
);
785 enabled
= (ifxmips_r32(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_IS_ENABLED
);
786 ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
788 br
= (((ifx_ssc_clock
>> 1) + baud
/ 2) / baud
) - 1;
791 if (br
> 0xffff || ((br
== 0) &&
792 ((ifxmips_r32(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_IS_MASTER
) == 0))) {
793 local_irq_restore(flags
);
794 printk("%s: invalid baudrate %u\n", __func__
, baud
);
798 ifxmips_w32(br
, IFXMIPS_SSC_BR
);
801 ifxmips_w32(IFX_SSC_WHBSTATE_SET_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
803 local_irq_restore(flags
);
809 static int ifx_ssc_hwinit(struct ifx_ssc_port
*info
)
814 enabled
= (ifxmips_r32(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_IS_ENABLED
);
815 ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
817 if (ifx_ssc_sethwopts(info
) < 0) {
818 printk("%s: setting the hardware options failed\n", __func__
);
822 if (ifx_ssc_set_baud(info
, info
->baud
) < 0) {
823 printk("%s: setting the baud rate failed\n", __func__
);
827 local_irq_save(flags
);
830 ifxmips_w32((IFX_SSC_DEF_TXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_ENABLE
, IFXMIPS_SSC_TXFCON
);
832 ifxmips_w32((IFX_SSC_DEF_RXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_ENABLE
, IFXMIPS_SSC_RXFCON
);
834 local_irq_restore(flags
);
837 ifxmips_w32(IFX_SSC_WHBSTATE_SET_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
842 int ifx_ssc_ioctl(struct inode
*inode
, struct file
*filp
,
843 unsigned int cmd
, unsigned long data
)
845 struct ifx_ssc_port
*info
;
846 int line
, ret_val
= 0;
851 if ((inode
== (struct inode
*)0) || (inode
== (struct inode
*)1)) {
855 line
= MINOR(filp
->f_dentry
->d_inode
->i_rdev
);
857 if (line
< 0 || line
>= PORT_CNT
)
863 case IFX_SSC_STATS_READ
:
864 /* data must be a pointer to a struct ifx_ssc_statistics */
866 memcpy((void *)data
, (void *)&info
->stats
,
867 sizeof(struct ifx_ssc_statistics
));
868 else if (copy_to_user((void *)data
,
869 (void *)&info
->stats
,
870 sizeof(struct ifx_ssc_statistics
)))
873 case IFX_SSC_STATS_RESET
:
874 /* just resets the statistics counters */
875 memset((void *)&info
->stats
, 0,
876 sizeof(struct ifx_ssc_statistics
));
878 case IFX_SSC_BAUD_SET
:
879 /* if the buffers are not empty then the port is */
880 /* busy and we shouldn't change things on-the-fly! */
881 if (!info
->txbuf
|| !info
->rxbuf
||
882 (ifxmips_r32(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_BUSY
)) {
888 flags
= *((unsigned long *)data
);
889 else if (copy_from_user((void *)&flags
,
890 (void *)data
, sizeof(flags
))) {
898 if (ifx_ssc_set_baud(info
, flags
) < 0) {
904 case IFX_SSC_BAUD_GET
:
906 *((unsigned int *)data
) = info
->baud
;
907 else if (copy_to_user((void *)data
,
909 sizeof(unsigned long)))
912 case IFX_SSC_RXTX_MODE_SET
:
914 tmp
= *((unsigned long *)data
);
915 else if (copy_from_user((void *)&tmp
,
916 (void *)data
, sizeof(tmp
))) {
920 ret_val
= ifx_ssc_rxtx_mode_set(info
, tmp
);
922 case IFX_SSC_RXTX_MODE_GET
:
923 tmp
= ifxmips_r32(IFXMIPS_SSC_CON
) &
924 (~(IFX_SSC_CON_RX_OFF
| IFX_SSC_CON_TX_OFF
));
926 *((unsigned int *)data
) = tmp
;
927 else if (copy_to_user((void *)data
,
928 (void *)&tmp
, sizeof(tmp
)))
936 case IFX_SSC_GPO_OUT_SET
:
938 tmp
= *((unsigned long *)data
);
939 else if (copy_from_user((void *)&tmp
,
940 (void *)data
, sizeof(tmp
))) {
944 if (tmp
> IFX_SSC_MAX_GPO_OUT
)
947 ifxmips_w32(1 << (tmp
+ IFX_SSC_WHBGPOSTAT_SETOUT0_POS
),
948 IFXMIPS_SSC_WHBGPOSTAT
);
950 case IFX_SSC_GPO_OUT_CLR
:
952 tmp
= *((unsigned long *)data
);
953 else if (copy_from_user((void *)&tmp
, (void *)data
, sizeof(tmp
))) {
957 if (tmp
> IFX_SSC_MAX_GPO_OUT
)
960 ifxmips_w32(1 << (tmp
+ IFX_SSC_WHBGPOSTAT_CLROUT0_POS
),
961 IFXMIPS_SSC_WHBGPOSTAT
);
963 case IFX_SSC_GPO_OUT_GET
:
964 tmp
= ifxmips_r32(IFXMIPS_SSC_GPOSTAT
);
966 *((unsigned int *)data
) = tmp
;
967 else if (copy_to_user((void *)data
,
968 (void *)&tmp
, sizeof(tmp
)))
971 case IFX_SSC_FRM_STATUS_GET
:
972 ifx_ssc_frm_status_get(info
);
974 memcpy((void *)data
, (void *)&info
->frm_status
,
975 sizeof(struct ifx_ssc_frm_status
));
976 else if (copy_to_user((void *)data
,
977 (void *)&info
->frm_status
,
978 sizeof(struct ifx_ssc_frm_status
)))
981 case IFX_SSC_FRM_CONTROL_GET
:
982 ifx_ssc_frm_control_get(info
);
984 memcpy((void *)data
, (void *)&info
->frm_opts
,
985 sizeof(struct ifx_ssc_frm_opts
));
986 else if (copy_to_user((void *)data
,
987 (void *)&info
->frm_opts
,
988 sizeof(struct ifx_ssc_frm_opts
)))
991 case IFX_SSC_FRM_CONTROL_SET
:
993 memcpy((void *)&info
->frm_opts
, (void *)data
,
994 sizeof(struct ifx_ssc_frm_opts
));
995 else if (copy_to_user((void *)&info
->frm_opts
,
997 sizeof(struct ifx_ssc_frm_opts
))) {
1001 ret_val
= ifx_ssc_frm_control_set(info
);
1003 case IFX_SSC_HWOPTS_SET
:
1004 /* data must be a pointer to a struct ifx_ssc_hwopts */
1005 /* if the buffers are not empty then the port is */
1006 /* busy and we shouldn't change things on-the-fly! */
1007 if (!info
->txbuf
|| !info
->rxbuf
||
1008 (ifxmips_r32(IFXMIPS_SSC_STATE
)
1009 & IFX_SSC_STATE_BUSY
)) {
1014 memcpy((void *)&info
->opts
, (void *)data
,
1015 sizeof(struct ifx_ssc_hwopts
));
1016 else if (copy_from_user((void *)&info
->opts
,
1017 (void *)data
, sizeof(struct ifx_ssc_hwopts
))) {
1021 if (ifx_ssc_hwinit(info
) < 0)
1024 case IFX_SSC_HWOPTS_GET
:
1025 /* data must be a pointer to a struct ifx_ssc_hwopts */
1027 memcpy((void *)data
, (void *)&info
->opts
,
1028 sizeof(struct ifx_ssc_hwopts
));
1029 else if (copy_to_user((void *)data
,
1030 (void *)&info
->opts
,
1031 sizeof(struct ifx_ssc_hwopts
)))
1035 ret_val
= -ENOIOCTLCMD
;
1040 EXPORT_SYMBOL(ifx_ssc_ioctl
);
1042 static struct file_operations ifx_ssc_fops
= {
1043 .owner
= THIS_MODULE
,
1044 .read
= ifx_ssc_read
,
1045 .write
= ifx_ssc_write
,
1046 .ioctl
= ifx_ssc_ioctl
,
1047 .open
= ifx_ssc_open
,
1048 .release
= ifx_ssc_close
,
1051 int __init
ifx_ssc_init(void)
1053 struct ifx_ssc_port
*info
;
1055 unsigned long flags
;
1059 nbytes
= PORT_CNT
* sizeof(struct ifx_ssc_port
);
1060 isp
= kmalloc(nbytes
, GFP_KERNEL
);
1063 printk("%s: no memory for isp\n", __func__
);
1066 memset(isp
, 0, nbytes
);
1069 i
= register_chrdev(maj
, "ssc", &ifx_ssc_fops
);
1071 printk("Unable to register major %d for the Infineon SSC\n", maj
);
1076 i
= register_chrdev(maj
, "ssc", &ifx_ssc_fops
);
1078 printk("Unable to register major %d for the Infineon SSC\n", maj
);
1087 /* set default values in ifx_ssc_port */
1088 for (i
= 0; i
< PORT_CNT
; i
++) {
1091 /* default values for the HwOpts */
1092 info
->opts
.AbortErrDetect
= IFX_SSC_DEF_ABRT_ERR_DETECT
;
1093 info
->opts
.rxOvErrDetect
= IFX_SSC_DEF_RO_ERR_DETECT
;
1094 info
->opts
.rxUndErrDetect
= IFX_SSC_DEF_RU_ERR_DETECT
;
1095 info
->opts
.txOvErrDetect
= IFX_SSC_DEF_TO_ERR_DETECT
;
1096 info
->opts
.txUndErrDetect
= IFX_SSC_DEF_TU_ERR_DETECT
;
1097 info
->opts
.loopBack
= IFX_SSC_DEF_LOOP_BACK
;
1098 info
->opts
.echoMode
= IFX_SSC_DEF_ECHO_MODE
;
1099 info
->opts
.idleValue
= IFX_SSC_DEF_IDLE_DATA
;
1100 info
->opts
.clockPolarity
= IFX_SSC_DEF_CLOCK_POLARITY
;
1101 info
->opts
.clockPhase
= IFX_SSC_DEF_CLOCK_PHASE
;
1102 info
->opts
.headingControl
= IFX_SSC_DEF_HEADING_CONTROL
;
1103 info
->opts
.dataWidth
= IFX_SSC_DEF_DATA_WIDTH
;
1104 info
->opts
.modeRxTx
= IFX_SSC_DEF_MODE_RXTX
;
1105 info
->opts
.gpoCs
= IFX_SSC_DEF_GPO_CS
;
1106 info
->opts
.gpoInv
= IFX_SSC_DEF_GPO_INV
;
1107 info
->opts
.masterSelect
= IFX_SSC_DEF_MASTERSLAVE
;
1108 info
->baud
= IFX_SSC_DEF_BAUDRATE
;
1111 /* values specific to SSC1 */
1113 info
->mapbase
= IFXMIPS_SSC_BASE_ADDR
;
1115 ifxmips_w32(IFX_SSC_DEF_RMC
<< IFX_CLC_RUN_DIVIDER_OFFSET
, IFXMIPS_SSC_CLC
);
1117 init_waitqueue_head(&info
->rwait
);
1119 local_irq_save(flags
);
1121 /* init serial framing register */
1122 ifxmips_w32(IFX_SSC_DEF_SFCON
, IFXMIPS_SSC_SFCON
);
1124 ret_val
= request_irq(IFXMIPS_SSC_TIR
, ifx_ssc_tx_int
, IRQF_DISABLED
, "ifx_ssc_tx", info
);
1126 printk("%s: unable to get irq %d\n", __func__
, IFXMIPS_SSC_TIR
);
1127 local_irq_restore(flags
);
1131 ret_val
= request_irq(IFXMIPS_SSC_RIR
, ifx_ssc_rx_int
, IRQF_DISABLED
, "ifx_ssc_rx", info
);
1133 printk("%s: unable to get irq %d\n", __func__
, IFXMIPS_SSC_RIR
);
1134 local_irq_restore(flags
);
1138 ret_val
= request_irq(IFXMIPS_SSC_EIR
, ifx_ssc_err_int
, IRQF_DISABLED
, "ifx_ssc_err", info
);
1140 printk("%s: unable to get irq %d\n", __func__
, IFXMIPS_SSC_EIR
);
1141 local_irq_restore(flags
);
1144 ifxmips_w32(IFX_SSC_DEF_IRNEN
, IFXMIPS_SSC_IRN
);
1147 enable_irq(IFXMIPS_SSC_TIR
);
1148 enable_irq(IFXMIPS_SSC_RIR
);
1149 enable_irq(IFXMIPS_SSC_EIR
);
1152 local_irq_restore(flags
);
1155 for (i
= 0; i
< PORT_CNT
; i
++) {
1157 if (ifx_ssc_hwinit(info
) < 0) {
1158 printk("%s: hardware init failed for port %d\n", __func__
, i
);
1167 free_irq(IFXMIPS_SSC_TIR
, &isp
[0]);
1168 free_irq(IFXMIPS_SSC_RIR
, &isp
[0]);
1169 free_irq(IFXMIPS_SSC_EIR
, &isp
[0]);
1175 void __exit
ifx_ssc_cleanup_module(void)
1179 for (i
= 0; i
< PORT_CNT
; i
++) {
1180 ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
1181 free_irq(IFXMIPS_SSC_TIR
, &isp
[i
]);
1182 free_irq(IFXMIPS_SSC_RIR
, &isp
[i
]);
1183 free_irq(IFXMIPS_SSC_EIR
, &isp
[i
]);
1188 module_init(ifx_ssc_init
);
1189 module_exit(ifx_ssc_cleanup_module
);
1191 inline int ifx_ssc_cs_low(u32 pin
)
1194 ret
= ifx_ssc_ioctl((struct inode
*)0, NULL
, IFX_SSC_GPO_OUT_CLR
, (unsigned long) &pin
);
1196 printk("clear CS %d fails\n", pin
);
1201 EXPORT_SYMBOL(ifx_ssc_cs_low
);
1203 inline int ifx_ssc_cs_high(u32 pin
)
1206 ret
= ifx_ssc_ioctl((struct inode
*)0, NULL
, IFX_SSC_GPO_OUT_SET
, (unsigned long) &pin
);
1208 printk("set CS %d fails\n", pin
);
1213 EXPORT_SYMBOL(ifx_ssc_cs_high
);
1215 static int ssc_session(char *tx_buf
, u32 tx_len
, char *rx_buf
, u32 rx_len
)
1219 char *ssc_tx_buf
= NULL
;
1220 char *ssc_rx_buf
= NULL
;
1224 if (tx_buf
== NULL
&& tx_len
== 0 && rx_buf
== NULL
&& rx_len
== 0) {
1225 printk("invalid parameters\n");
1227 goto ssc_session_exit
;
1228 } else if (tx_buf
== NULL
|| tx_len
== 0) {
1229 if (rx_buf
!= NULL
&& rx_len
!= 0) {
1230 mode
= IFX_SSC_MODE_RX
;
1232 printk("invalid parameters\n");
1234 goto ssc_session_exit
;
1236 } else if (rx_buf
== NULL
|| rx_len
== 0) {
1237 if (tx_buf
!= NULL
&& tx_len
!= 0)
1238 mode
= IFX_SSC_MODE_TX
;
1240 printk("invalid parameters\n");
1242 goto ssc_session_exit
;
1245 mode
= IFX_SSC_MODE_RXTX
;
1247 if (mode
== IFX_SSC_MODE_RXTX
)
1248 eff_size
= tx_len
+ rx_len
;
1249 else if (mode
== IFX_SSC_MODE_RX
)
1254 /* 4 bytes alignment, required by driver */
1255 ssc_tx_buf
= kmalloc(sizeof(char) *
1256 ((eff_size
+ 3) & (~3)),
1258 ssc_rx_buf
= kmalloc(sizeof(char) *
1259 ((eff_size
+ 3) & (~3)),
1261 if (ssc_tx_buf
== NULL
|| ssc_rx_buf
== NULL
) {
1262 printk("no memory for size of %d\n", eff_size
);
1264 goto ssc_session_exit
;
1266 memset((void *)ssc_tx_buf
, 0, eff_size
);
1267 memset((void *)ssc_rx_buf
, 0, eff_size
);
1270 memcpy(ssc_tx_buf
, tx_buf
, tx_len
);
1272 ret
= ifx_ssc_kwrite(0, ssc_tx_buf
, eff_size
);
1275 ssc_tx_buf
= NULL
; /* should be freed by ifx_ssc_kwrite */
1277 if (ret
!= eff_size
) {
1278 printk("ifx_ssc_write return %d\n", ret
);
1279 goto ssc_session_exit
;
1281 ret
= ifx_ssc_kread(0, ssc_rx_buf
, eff_size
);
1282 if (ret
!= eff_size
) {
1283 printk("ifx_ssc_read return %d\n", ret
);
1284 goto ssc_session_exit
;
1287 memcpy(rx_buf
, ssc_rx_buf
+ tx_len
, rx_len
);
1289 if (mode
== IFX_SSC_MODE_TX
)
1295 if (ssc_tx_buf
!= NULL
)
1297 if (ssc_rx_buf
!= NULL
)
1301 printk("ssc session fails\n");
1306 int ifx_ssc_txrx(char *tx_buf
, u32 tx_len
, char *rx_buf
, u32 rx_len
)
1308 return ssc_session(tx_buf
, tx_len
, rx_buf
, rx_len
);
1310 EXPORT_SYMBOL(ifx_ssc_txrx
);
1312 int ifx_ssc_tx(char *tx_buf
, u32 tx_len
)
1314 return ssc_session(tx_buf
, tx_len
, NULL
, 0);
1316 EXPORT_SYMBOL(ifx_ssc_tx
);
1318 int ifx_ssc_rx(char *rx_buf
, u32 rx_len
)
1320 return ssc_session(NULL
, 0, rx_buf
, rx_len
);
1322 EXPORT_SYMBOL(ifx_ssc_rx
);
1324 MODULE_LICENSE("GPL");
1325 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
1326 MODULE_DESCRIPTION("ifxmips ssc driver");