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 #ifdef SSC_FRAME_INT_ENABLE
62 #undef SSC_FRAME_INT_ENABLE
71 /* allow the user to set the major device number */
75 * This is the per-channel data structure containing pointers, flags
76 * and variables for the port. This driver supports a maximum of PORT_CNT.
77 * isp is allocated in ifx_ssc_init() based on the chip version.
79 static struct ifx_ssc_port
*isp
;
81 /* prototypes for fops */
82 static ssize_t
ifx_ssc_read (struct file
*, char *, size_t, loff_t
*);
83 static ssize_t
ifx_ssc_write (struct file
*, const char *, size_t, loff_t
*);
84 //static unsigned int ifx_ssc_poll(struct file *, struct poll_table_struct *);
85 int ifx_ssc_ioctl (struct inode
*, struct file
*, unsigned int,
87 int ifx_ssc_open (struct inode
*, struct file
*);
88 int ifx_ssc_close (struct inode
*, struct file
*);
90 /* other forward declarations */
91 static unsigned int ifx_ssc_get_kernel_clk (struct ifx_ssc_port
*info
);
92 static void tx_int (struct ifx_ssc_port
*);
94 extern unsigned int ifxmips_get_fpi_hz (void);
95 extern void mask_and_ack_ifxmips_irq (unsigned int irq_nr
);
97 static struct file_operations ifx_ssc_fops
= {
100 .write
= ifx_ssc_write
,
101 .ioctl
= ifx_ssc_ioctl
,
102 .open
= ifx_ssc_open
,
103 .release
= ifx_ssc_close
,
106 static inline unsigned int
107 ifx_ssc_get_kernel_clk (struct ifx_ssc_port
*info
)
111 rmc
= (readl(IFXMIPS_SSC_CLC
) & IFX_CLC_RUN_DIVIDER_MASK
) >> IFX_CLC_RUN_DIVIDER_OFFSET
;
114 printk ("ifx_ssc_get_kernel_clk rmc==0 \n");
117 return ifxmips_get_fpi_hz () / rmc
;
121 #ifdef IFX_SSC_INT_USE_BH
123 * This routine is used by the interrupt handler to schedule
124 * processing in the software interrupt portion of the driver
125 * (also known as the "bottom half"). This can be called any
126 * number of times for any channel without harm.
129 ifx_ssc_sched_event (struct ifx_ssc_port
*info
, int event
)
131 info
->event
|= 1 << event
; /* remember what kind of event and who */
132 queue_task (&info
->tqueue
, &tq_cyclades
); /* it belongs to */
133 mark_bh (CYCLADES_BH
); /* then trigger event */
137 do_softint (void *private_
)
139 struct ifx_ssc_port
*info
= (struct ifx_ssc_port
*) private_
;
141 if (test_and_clear_bit (Cy_EVENT_HANGUP
, &info
->event
))
143 wake_up_interruptible (&info
->open_wait
);
144 info
->flags
&= ~(ASYNC_NORMAL_ACTIVE
| ASYNC_CALLOUT_ACTIVE
);
147 if (test_and_clear_bit (Cy_EVENT_OPEN_WAKEUP
, &info
->event
))
148 wake_up_interruptible (&info
->open_wait
);
150 if (test_and_clear_bit (Cy_EVENT_DELTA_WAKEUP
, &info
->event
))
151 wake_up_interruptible (&info
->delta_msr_wait
);
153 if (test_and_clear_bit (Cy_EVENT_WRITE_WAKEUP
, &info
->event
))
154 wake_up_interruptible (&tty
->write_wait
);
156 if (test_and_clear_bit (Cy_EVENT_SHUTDOWN_WAKEUP
, &info
->event
))
157 wake_up_interruptible (&info
->shutdown_wait
);
164 rx_int (struct ifx_ssc_port
*info
)
166 int fifo_fill_lev
, bytes_in_buf
, i
;
167 unsigned long tmp_val
;
168 unsigned long *tmp_ptr
;
169 unsigned int rx_valid_cnt
;
170 /* number of words waiting in the RX FIFO */
171 fifo_fill_lev
= (readl(IFXMIPS_SSC_FSTAT
) & IFX_SSC_FSTAT_RECEIVED_WORDS_MASK
) >> IFX_SSC_FSTAT_RECEIVED_WORDS_OFFSET
;
172 bytes_in_buf
= info
->rxbuf_end
- info
->rxbuf_ptr
;
173 // transfer with 32 bits per entry
174 while ((bytes_in_buf
>= 4) && (fifo_fill_lev
> 0)) {
175 tmp_ptr
= (unsigned long *) info
->rxbuf_ptr
;
176 *tmp_ptr
= readl(IFXMIPS_SSC_RB
);
177 info
->rxbuf_ptr
+= 4;
178 info
->stats
.rxBytes
+= 4;
183 // now do the rest as mentioned in STATE.RXBV
184 while ((bytes_in_buf
> 0) && (fifo_fill_lev
> 0)) {
185 rx_valid_cnt
= (readl(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_RX_BYTE_VALID_MASK
) >> IFX_SSC_STATE_RX_BYTE_VALID_OFFSET
;
186 if (rx_valid_cnt
== 0)
189 if (rx_valid_cnt
> bytes_in_buf
)
190 rx_valid_cnt
= bytes_in_buf
;
192 tmp_val
= readl(IFXMIPS_SSC_RB
);
194 for (i
= 0; i
< rx_valid_cnt
; i
++)
196 *info
->rxbuf_ptr
= (tmp_val
>> (8 * (rx_valid_cnt
- i
- 1))) & 0xff;
200 info
->stats
.rxBytes
+= rx_valid_cnt
;
203 // check if transfer is complete
204 if (info
->rxbuf_ptr
>= info
->rxbuf_end
)
206 disable_irq(info
->rxirq
);
207 wake_up_interruptible (&info
->rwait
);
208 } else if ((info
->opts
.modeRxTx
== IFX_SSC_MODE_RX
) && (READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_RXCNT
) == 0))
210 if (info
->rxbuf_end
- info
->rxbuf_ptr
< IFX_SSC_RXREQ_BLOCK_SIZE
)
211 writel((info
->rxbuf_end
- info
->rxbuf_ptr
) << IFX_SSC_RXREQ_RXCOUNT_OFFSET
, IFXMIPS_SSC_RXREQ
);
213 writel(IFX_SSC_RXREQ_BLOCK_SIZE
<< IFX_SSC_RXREQ_RXCOUNT_OFFSET
, IFXMIPS_SSC_RXREQ
);
218 tx_int (struct ifx_ssc_port
*info
)
221 int fifo_space
, fill
, i
;
222 fifo_space
= ((readl(IFXMIPS_SSC_ID
) & IFX_SSC_PERID_TXFS_MASK
) >> IFX_SSC_PERID_TXFS_OFFSET
)
223 - ((readl(IFXMIPS_SSC_FSTAT
) & IFX_SSC_FSTAT_TRANSMIT_WORDS_MASK
) >> IFX_SSC_FSTAT_TRANSMIT_WORDS_OFFSET
);
228 fill
= info
->txbuf_end
- info
->txbuf_ptr
;
230 if (fill
> fifo_space
* 4)
231 fill
= fifo_space
* 4;
233 for (i
= 0; i
< fill
/ 4; i
++)
235 // at first 32 bit access
236 writel(*(UINT32
*) info
->txbuf_ptr
, IFXMIPS_SSC_TB
);
237 info
->txbuf_ptr
+= 4;
240 fifo_space
-= fill
/ 4;
241 info
->stats
.txBytes
+= fill
& ~0x3;
243 if ((fifo_space
> 0) & (fill
> 1))
245 // trailing 16 bit access
246 WRITE_PERIPHERAL_REGISTER_16 (*(UINT16
*) info
->txbuf_ptr
, info
->mapbase
+ IFX_SSC_TB
);
247 info
->txbuf_ptr
+= 2;
248 info
->stats
.txBytes
+= 2;
253 if ((fifo_space
> 0) & (fill
> 0))
255 // trailing 8 bit access
256 WRITE_PERIPHERAL_REGISTER_8 (*(UINT8
*) info
->txbuf_ptr
, info
->mapbase
+ IFX_SSC_TB
);
258 info
->stats
.txBytes
++;
261 // check if transmission complete
262 if (info
->txbuf_ptr
>= info
->txbuf_end
)
264 disable_irq(info
->txirq
);
272 ifx_ssc_rx_int (int irq
, void *dev_id
)
274 struct ifx_ssc_port
*info
= (struct ifx_ssc_port
*) dev_id
;
281 ifx_ssc_tx_int (int irq
, void *dev_id
)
283 struct ifx_ssc_port
*info
= (struct ifx_ssc_port
*) dev_id
;
290 ifx_ssc_err_int (int irq
, void *dev_id
)
292 struct ifx_ssc_port
*info
= (struct ifx_ssc_port
*) dev_id
;
294 unsigned int write_back
= 0;
297 local_irq_save (flags
);
298 state
= readl(IFXMIPS_SSC_STATE
);
300 if ((state
& IFX_SSC_STATE_RX_UFL
) != 0) {
301 info
->stats
.rxUnErr
++;
302 write_back
|= IFX_SSC_WHBSTATE_CLR_RX_UFL_ERROR
;
305 if ((state
& IFX_SSC_STATE_RX_OFL
) != 0) {
306 info
->stats
.rxOvErr
++;
307 write_back
|= IFX_SSC_WHBSTATE_CLR_RX_OFL_ERROR
;
310 if ((state
& IFX_SSC_STATE_TX_OFL
) != 0) {
311 info
->stats
.txOvErr
++;
312 write_back
|= IFX_SSC_WHBSTATE_CLR_TX_OFL_ERROR
;
315 if ((state
& IFX_SSC_STATE_TX_UFL
) != 0) {
316 info
->stats
.txUnErr
++;
317 write_back
|= IFX_SSC_WHBSTATE_CLR_TX_UFL_ERROR
;
320 if ((state
& IFX_SSC_STATE_MODE_ERR
) != 0) {
321 info
->stats
.modeErr
++;
322 write_back
|= IFX_SSC_WHBSTATE_CLR_MODE_ERROR
;
326 writel(write_back
, IFXMIPS_SSC_WHBSTATE
);
328 local_irq_restore (flags
);
334 ifx_ssc_abort (struct ifx_ssc_port
*info
)
339 local_irq_save (flags
);
341 disable_irq(info
->rxirq
);
342 disable_irq(info
->txirq
);
343 disable_irq(info
->errirq
);
345 local_irq_restore (flags
);
347 // disable SSC (also aborts a receive request!)
348 // ### TO DO: Perhaps it's better to abort after the receiption of a
349 // complete word. The disable cuts the transmission immediatly and
350 // releases the chip selects. This could result in unpredictable
351 // behavior of connected external devices!
352 enabled
= (readl(IFXMIPS_SSC_STATE
) & IFX_SSC_STATE_IS_ENABLED
) != 0;
353 writel(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
356 writel(IFX_SSC_XFCON_FIFO_FLUSH
, IFXMIPS_SSC_TXFCON
);
357 writel(IFX_SSC_XFCON_FIFO_FLUSH
, IFXMIPS_SSC_RXFCON
);
360 if (info
->txbuf
!= NULL
)
366 // wakeup read process
367 if (info
->rxbuf
!= NULL
)
368 wake_up_interruptible (&info
->rwait
);
370 // clear pending int's
371 mask_and_ack_ifxmips_irq(info
->rxirq
);
372 mask_and_ack_ifxmips_irq(info
->txirq
);
373 mask_and_ack_ifxmips_irq(info
->errirq
);
376 writel(IFX_SSC_WHBSTATE_CLR_ALL_ERROR
, IFXMIPS_SSC_WHBSTATE
);
379 writel(IFX_SSC_WHBSTATE_SET_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
384 * This routine is called whenever a port is opened. It enforces
385 * exclusive opening of a port and enables interrupts, etc.
388 ifx_ssc_open (struct inode
*inode
, struct file
*filp
)
390 struct ifx_ssc_port
*info
;
394 if ((inode
== (struct inode
*) 0) || (inode
== (struct inode
*) 1)) {
398 line
= MINOR (filp
->f_dentry
->d_inode
->i_rdev
);
399 filp
->f_op
= &ifx_ssc_fops
;
402 /* don't open more minor devices than we can support */
403 if (line
< 0 || line
>= PORT_CNT
)
409 if (info
->port_is_open
!= 0)
411 info
->port_is_open
++;
413 disable_irq(info
->rxirq
);
414 disable_irq(info
->txirq
);
415 disable_irq(info
->errirq
);
417 /* Flush and enable TX/RX FIFO */
418 writel((IFX_SSC_DEF_TXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_FLUSH
| IFX_SSC_XFCON_FIFO_ENABLE
, IFXMIPS_SSC_TXFCON
);
419 writel((IFX_SSC_DEF_RXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_FLUSH
| IFX_SSC_XFCON_FIFO_ENABLE
, IFXMIPS_SSC_RXFCON
);
421 /* logically flush the software FIFOs */
425 /* clear all error bits */
426 writel(IFX_SSC_WHBSTATE_CLR_ALL_ERROR
, IFXMIPS_SSC_WHBSTATE
);
428 // clear pending interrupts
429 mask_and_ack_ifxmips_irq(info
->rxirq
);
430 mask_and_ack_ifxmips_irq(info
->txirq
);
431 mask_and_ack_ifxmips_irq(info
->errirq
);
433 writel(IFX_SSC_WHBSTATE_SET_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
437 EXPORT_SYMBOL(ifx_ssc_open
);
440 ifx_ssc_close (struct inode
*inode
, struct file
*filp
)
442 struct ifx_ssc_port
*info
;
445 if ((inode
== (struct inode
*) 0) || (inode
== (struct inode
*) 1))
448 idx
= MINOR (filp
->f_dentry
->d_inode
->i_rdev
);
450 if (idx
< 0 || idx
>= PORT_CNT
)
457 writel(IFX_SSC_WHBSTATE_CLR_ENABLE
, IFXMIPS_SSC_WHBSTATE
);
461 info
->port_is_open
--;
465 EXPORT_SYMBOL(ifx_ssc_close
);
468 ifx_ssc_read_helper_poll (struct ifx_ssc_port
*info
, char *buf
, size_t len
, int from_kernel
)
473 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
;
478 local_irq_restore (flags
);
479 /* Vinetic driver always works in IFX_SSC_MODE_RXTX */
480 /* TXRX in poll mode */
481 while (info
->rxbuf_ptr
< info
->rxbuf_end
)
483 if (info
->txbuf_ptr
< info
->txbuf_end
)
489 ret_val
= info
->rxbuf_ptr
- info
->rxbuf
;
495 ifx_ssc_read_helper (struct ifx_ssc_port
*info
, char *buf
, size_t len
, int from_kernel
)
499 DECLARE_WAITQUEUE (wait
, current
);
501 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_TX
)
504 local_irq_save (flags
);
505 info
->rxbuf_ptr
= info
->rxbuf
;
506 info
->rxbuf_end
= info
->rxbuf
+ len
;
508 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_RXTX
)
510 if ((info
->txbuf
== NULL
) || (info
->txbuf
!= info
->txbuf_ptr
) || (info
->txbuf_end
!= len
+ info
->txbuf
))
512 local_irq_restore (flags
);
513 printk ("IFX SSC - %s: write must be called before calling " "read in combined RX/TX!\n", __func__
);
517 local_irq_restore(flags
);
520 if (info
->txbuf_ptr
< info
->txbuf_end
)
521 enable_irq(info
->txirq
);
523 enable_irq(info
->rxirq
);
525 local_irq_restore(flags
);
526 if (READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_RXCNT
) & IFX_SSC_RXCNT_TODO_MASK
)
528 enable_irq(info
->rxirq
);
529 if (len
< IFX_SSC_RXREQ_BLOCK_SIZE
)
530 WRITE_PERIPHERAL_REGISTER (len
<< IFX_SSC_RXREQ_RXCOUNT_OFFSET
, info
->mapbase
+ IFX_SSC_RXREQ
);
532 WRITE_PERIPHERAL_REGISTER (IFX_SSC_RXREQ_BLOCK_SIZE
<< IFX_SSC_RXREQ_RXCOUNT_OFFSET
, info
->mapbase
+ IFX_SSC_RXREQ
);
535 __add_wait_queue (&info
->rwait
, &wait
);
536 set_current_state (TASK_INTERRUPTIBLE
);
539 local_irq_save (flags
);
540 if (info
->rxbuf_ptr
>= info
->rxbuf_end
)
543 local_irq_restore (flags
);
545 if (signal_pending (current
))
547 ret_val
= -ERESTARTSYS
;
553 ret_val
= info
->rxbuf_ptr
- info
->rxbuf
;
554 local_irq_restore (flags
);
557 current
->state
= TASK_RUNNING
;
558 __remove_wait_queue (&info
->rwait
, &wait
);
564 ifx_ssc_write_helper (struct ifx_ssc_port
*info
, const char *buf
,
565 size_t len
, int from_kernel
)
567 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_RX
)
570 info
->txbuf_ptr
= info
->txbuf
;
571 info
->txbuf_end
= len
+ info
->txbuf
;
572 if (info
->opts
.modeRxTx
== IFX_SSC_MODE_TX
)
575 if (info
->txbuf_ptr
< info
->txbuf_end
)
577 enable_irq(info
->txirq
);
585 ifx_ssc_kread (int port
, char *kbuf
, size_t len
)
587 struct ifx_ssc_port
*info
;
590 if (port
< 0 || port
>= PORT_CNT
)
598 if (info
->rxbuf
!= NULL
)
600 printk ("SSC device busy\n");
605 if (info
->rxbuf
== NULL
)
607 printk ("SSC device error\n");
611 ret_val
= ifx_ssc_read_helper_poll (info
, kbuf
, len
, 1);
614 disable_irq(info
->rxirq
);
618 EXPORT_SYMBOL(ifx_ssc_kread
);
621 ifx_ssc_kwrite (int port
, const char *kbuf
, size_t len
)
623 struct ifx_ssc_port
*info
;
626 if (port
< 0 || port
>= PORT_CNT
)
634 // check if transmission in progress
635 if (info
->txbuf
!= NULL
)
638 info
->txbuf
= (char *) kbuf
;
640 ret_val
= ifx_ssc_write_helper (info
, info
->txbuf
, len
, 1);
647 EXPORT_SYMBOL(ifx_ssc_kwrite
);
650 ifx_ssc_read (struct file
*filp
, char *ubuf
, size_t len
, loff_t
* off
)
654 struct ifx_ssc_port
*info
;
656 idx
= MINOR (filp
->f_dentry
->d_inode
->i_rdev
);
659 if (info
->rxbuf
!= NULL
)
662 info
->rxbuf
= kmalloc (len
+ 3, GFP_KERNEL
);
663 if (info
->rxbuf
== NULL
)
666 ret_val
= ifx_ssc_read_helper (info
, info
->rxbuf
, len
, 0);
667 if (copy_to_user ((void *) ubuf
, info
->rxbuf
, ret_val
) != 0)
670 disable_irq(info
->rxirq
);
679 ifx_ssc_write (struct file
*filp
, const char *ubuf
, size_t len
, loff_t
* off
)
682 struct ifx_ssc_port
*info
;
688 idx
= MINOR (filp
->f_dentry
->d_inode
->i_rdev
);
691 if (info
->txbuf
!= NULL
)
694 info
->txbuf
= kmalloc (len
+ 3, GFP_KERNEL
);
695 if (info
->txbuf
== NULL
)
698 ret_val
= copy_from_user (info
->txbuf
, ubuf
, len
);
700 ret_val
= ifx_ssc_write_helper (info
, info
->txbuf
, len
, 0);
713 static struct ifx_ssc_frm_status
*
714 ifx_ssc_frm_status_get (struct ifx_ssc_port
*info
)
718 tmp
= readl(IFXMIPS_SSC_SFSTAT
);
719 info
->frm_status
.DataBusy
= (tmp
& IFX_SSC_SFSTAT_IN_DATA
) > 0;
720 info
->frm_status
.PauseBusy
= (tmp
& IFX_SSC_SFSTAT_IN_PAUSE
) > 0;
721 info
->frm_status
.DataCount
= (tmp
& IFX_SSC_SFSTAT_DATA_COUNT_MASK
) >> IFX_SSC_SFSTAT_DATA_COUNT_OFFSET
;
722 info
->frm_status
.PauseCount
= (tmp
& IFX_SSC_SFSTAT_PAUSE_COUNT_MASK
) >> IFX_SSC_SFSTAT_PAUSE_COUNT_OFFSET
;
723 tmp
= READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_SFCON
);
724 info
->frm_status
.EnIntAfterData
= (tmp
& IFX_SSC_SFCON_FIR_ENABLE_BEFORE_PAUSE
) > 0;
725 info
->frm_status
.EnIntAfterPause
= (tmp
& IFX_SSC_SFCON_FIR_ENABLE_AFTER_PAUSE
) > 0;
727 return &info
->frm_status
;
731 static struct ifx_ssc_frm_opts
*
732 ifx_ssc_frm_control_get (struct ifx_ssc_port
*info
)
736 tmp
= READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_SFCON
);
737 info
->frm_opts
.FrameEnable
= (tmp
& IFX_SSC_SFCON_SF_ENABLE
) > 0;
738 info
->frm_opts
.DataLength
= (tmp
& IFX_SSC_SFCON_DATA_LENGTH_MASK
) >> IFX_SSC_SFCON_DATA_LENGTH_OFFSET
;
739 info
->frm_opts
.PauseLength
= (tmp
& IFX_SSC_SFCON_PAUSE_LENGTH_MASK
) >> IFX_SSC_SFCON_PAUSE_LENGTH_OFFSET
;
740 info
->frm_opts
.IdleData
= (tmp
& IFX_SSC_SFCON_PAUSE_DATA_MASK
) >> IFX_SSC_SFCON_PAUSE_DATA_OFFSET
;
741 info
->frm_opts
.IdleClock
= (tmp
& IFX_SSC_SFCON_PAUSE_CLOCK_MASK
) >> IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET
;
742 info
->frm_opts
.StopAfterPause
= (tmp
& IFX_SSC_SFCON_STOP_AFTER_PAUSE
) > 0;
744 return &info
->frm_opts
;
748 ifx_ssc_frm_control_set (struct ifx_ssc_port
*info
)
753 if ((info
->frm_opts
.DataLength
> IFX_SSC_SFCON_DATA_LENGTH_MAX
)
754 || (info
->frm_opts
.DataLength
< 1)
755 || (info
->frm_opts
.PauseLength
> IFX_SSC_SFCON_PAUSE_LENGTH_MAX
)
756 || (info
->frm_opts
.PauseLength
< 1)
757 || (info
->frm_opts
.IdleData
& ~(IFX_SSC_SFCON_PAUSE_DATA_MASK
>> IFX_SSC_SFCON_PAUSE_DATA_OFFSET
))
758 || (info
->frm_opts
.IdleClock
& ~(IFX_SSC_SFCON_PAUSE_CLOCK_MASK
>> IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET
)))
761 // read interrupt bits (they're not changed here)
762 tmp
= READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_SFCON
) &
763 (IFX_SSC_SFCON_FIR_ENABLE_BEFORE_PAUSE
| IFX_SSC_SFCON_FIR_ENABLE_AFTER_PAUSE
);
765 // set all values with respect to it's bit position (for data and pause
767 tmp
= (info
->frm_opts
.DataLength
- 1) << IFX_SSC_SFCON_DATA_LENGTH_OFFSET
;
768 tmp
|= (info
->frm_opts
.PauseLength
- 1) << IFX_SSC_SFCON_PAUSE_LENGTH_OFFSET
;
769 tmp
|= info
->frm_opts
.IdleData
<< IFX_SSC_SFCON_PAUSE_DATA_OFFSET
;
770 tmp
|= info
->frm_opts
.IdleClock
<< IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET
;
771 tmp
|= info
->frm_opts
.FrameEnable
* IFX_SSC_SFCON_SF_ENABLE
;
772 tmp
|= info
->frm_opts
.StopAfterPause
* IFX_SSC_SFCON_STOP_AFTER_PAUSE
;
774 WRITE_PERIPHERAL_REGISTER(tmp
, info
->mapbase
+ IFX_SSC_SFCON
);
780 ifx_ssc_rxtx_mode_set (struct ifx_ssc_port
*info
, unsigned int val
)
784 if (!(info
) || (val
& ~(IFX_SSC_MODE_MASK
)))
787 if ((READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_STATE
) & IFX_SSC_STATE_BUSY
)
788 || (READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_RXCNT
) & IFX_SSC_RXCNT_TODO_MASK
))
791 tmp
= (READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_CON
) & ~(IFX_SSC_CON_RX_OFF
| IFX_SSC_CON_TX_OFF
)) | (val
);
792 WRITE_PERIPHERAL_REGISTER (tmp
, info
->mapbase
+ IFX_SSC_CON
);
793 info
->opts
.modeRxTx
= val
;
799 ifx_ssc_sethwopts (struct ifx_ssc_port
*info
)
801 unsigned long flags
, bits
;
802 struct ifx_ssc_hwopts
*opts
= &info
->opts
;
804 if ((opts
->dataWidth
< IFX_SSC_MIN_DATA_WIDTH
)
805 || (opts
->dataWidth
> IFX_SSC_MAX_DATA_WIDTH
))
808 bits
= (opts
->dataWidth
- 1) << IFX_SSC_CON_DATA_WIDTH_OFFSET
;
809 bits
|= IFX_SSC_CON_ENABLE_BYTE_VALID
;
811 if (opts
->rxOvErrDetect
)
812 bits
|= IFX_SSC_CON_RX_OFL_CHECK
;
813 if (opts
->rxUndErrDetect
)
814 bits
|= IFX_SSC_CON_RX_UFL_CHECK
;
815 if (opts
->txOvErrDetect
)
816 bits
|= IFX_SSC_CON_TX_OFL_CHECK
;
817 if (opts
->txUndErrDetect
)
818 bits
|= IFX_SSC_CON_TX_UFL_CHECK
;
820 bits
|= IFX_SSC_CON_LOOPBACK_MODE
;
822 bits
|= IFX_SSC_CON_ECHO_MODE_ON
;
823 if (opts
->headingControl
)
824 bits
|= IFX_SSC_CON_MSB_FIRST
;
825 if (opts
->clockPhase
)
826 bits
|= IFX_SSC_CON_LATCH_THEN_SHIFT
;
827 if (opts
->clockPolarity
)
828 bits
|= IFX_SSC_CON_CLOCK_FALL
;
830 switch (opts
->modeRxTx
)
832 case IFX_SSC_MODE_TX
:
833 bits
|= IFX_SSC_CON_RX_OFF
;
835 case IFX_SSC_MODE_RX
:
836 bits
|= IFX_SSC_CON_TX_OFF
;
840 local_irq_save (flags
);
842 WRITE_PERIPHERAL_REGISTER (bits
, info
->mapbase
+ IFX_SSC_CON
);
843 WRITE_PERIPHERAL_REGISTER ((info
->opts
.gpoCs
<< IFX_SSC_GPOCON_ISCSB0_POS
) |
844 (info
->opts
.gpoInv
<< IFX_SSC_GPOCON_INVOUT0_POS
), info
->mapbase
+ IFX_SSC_GPOCON
);
846 WRITE_PERIPHERAL_REGISTER (info
->opts
.gpoCs
<< IFX_SSC_WHBGPOSTAT_SETOUT0_POS
, info
->mapbase
+ IFX_SSC_WHBGPOSTAT
);
849 if (opts
->masterSelect
)
850 WRITE_PERIPHERAL_REGISTER (IFX_SSC_WHBSTATE_SET_MASTER_SELECT
, info
->mapbase
+ IFX_SSC_WHBSTATE
);
852 WRITE_PERIPHERAL_REGISTER (IFX_SSC_WHBSTATE_CLR_MASTER_SELECT
, info
->mapbase
+ IFX_SSC_WHBSTATE
);
854 // init serial framing
855 WRITE_PERIPHERAL_REGISTER (0, info
->mapbase
+ IFX_SSC_SFCON
);
856 /* set up the port pins */
857 //check for general requirements to switch (external) pad/pin characteristics
858 /* TODO: P0.9 SPI_CS4, P0.10 SPI_CS5, P 0.11 SPI_CS6, because of ASC0 */
859 /* p0.15 SPI_CS1(EEPROM), P0.13 SPI_CS3, */
860 /* Set p0.15 to alternative 01, others to 00 (In/OUT) */
861 *(IFXMIPS_GPIO_P0_DIR
) = (*IFXMIPS_GPIO_P0_DIR
) | (0xA000);
862 *(IFXMIPS_GPIO_P0_ALTSEL0
) = (((*IFXMIPS_GPIO_P0_ALTSEL0
) | (0x8000)) & (~(0x2000)));
863 *(IFXMIPS_GPIO_P0_ALTSEL1
) = (((*IFXMIPS_GPIO_P0_ALTSEL1
) & (~0x8000)) & (~(0x2000)));
864 *(IFXMIPS_GPIO_P0_OD
) = (*IFXMIPS_GPIO_P0_OD
) | 0xA000;
866 /* p1.6 SPI_CS2(SFLASH), p1.0 SPI_DIN, p1.1 SPI_DOUT, p1.2 SPI_CLK */
867 *(IFXMIPS_GPIO_P1_DIR
) = ((*IFXMIPS_GPIO_P1_DIR
) | (0x46)) & (~1);
868 *(IFXMIPS_GPIO_P1_ALTSEL0
) = ((*IFXMIPS_GPIO_P1_ALTSEL0
) | (0x47));
869 *(IFXMIPS_GPIO_P1_ALTSEL1
) = (*IFXMIPS_GPIO_P1_ALTSEL1
) & (~0x47);
870 *(IFXMIPS_GPIO_P1_OD
) = (*IFXMIPS_GPIO_P1_OD
) | 0x0046;
873 /*TODO: CS4 CS5 CS6 */
874 *IFXMIPS_GPIO_P0_OUT
= ((*IFXMIPS_GPIO_P0_OUT
) | 0x2000);
876 local_irq_restore (flags
);
882 ifx_ssc_set_baud (struct ifx_ssc_port
*info
, unsigned int baud
)
884 unsigned int ifx_ssc_clock
;
890 ifx_ssc_clock
= ifx_ssc_get_kernel_clk(info
);
891 if (ifx_ssc_clock
== 0)
897 local_irq_save (flags
);
899 enabled
= (READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_STATE
) & IFX_SSC_STATE_IS_ENABLED
);
900 WRITE_PERIPHERAL_REGISTER (IFX_SSC_WHBSTATE_CLR_ENABLE
, info
->mapbase
+ IFX_SSC_WHBSTATE
);
902 br
= (((ifx_ssc_clock
>> 1) + baud
/ 2) / baud
) - 1;
905 if (br
> 0xffff || ((br
== 0) &&
906 ((READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_STATE
) & IFX_SSC_STATE_IS_MASTER
) == 0))) {
907 local_irq_restore (flags
);
908 printk ("%s: invalid baudrate %u\n", __func__
, baud
);
912 WRITE_PERIPHERAL_REGISTER (br
, info
->mapbase
+ IFX_SSC_BR
);
915 WRITE_PERIPHERAL_REGISTER (IFX_SSC_WHBSTATE_SET_ENABLE
, info
->mapbase
+ IFX_SSC_WHBSTATE
);
917 local_irq_restore(flags
);
924 ifx_ssc_hwinit (struct ifx_ssc_port
*info
)
929 enabled
= (READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_STATE
) & IFX_SSC_STATE_IS_ENABLED
);
930 WRITE_PERIPHERAL_REGISTER (IFX_SSC_WHBSTATE_CLR_ENABLE
, info
->mapbase
+ IFX_SSC_WHBSTATE
);
932 if (ifx_ssc_sethwopts (info
) < 0)
934 printk ("%s: setting the hardware options failed\n", __func__
);
938 if (ifx_ssc_set_baud (info
, info
->baud
) < 0)
940 printk ("%s: setting the baud rate failed\n", __func__
);
944 local_irq_save (flags
);
947 WRITE_PERIPHERAL_REGISTER ((IFX_SSC_DEF_TXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_ENABLE
,
948 info
->mapbase
+ IFX_SSC_TXFCON
);
950 WRITE_PERIPHERAL_REGISTER ((IFX_SSC_DEF_RXFIFO_FL
<< IFX_SSC_XFCON_ITL_OFFSET
) | IFX_SSC_XFCON_FIFO_ENABLE
,
951 info
->mapbase
+ IFX_SSC_RXFCON
);
953 local_irq_restore (flags
);
956 WRITE_PERIPHERAL_REGISTER (IFX_SSC_WHBSTATE_SET_ENABLE
, info
->mapbase
+ IFX_SSC_WHBSTATE
);
962 ifx_ssc_ioctl (struct inode
*inode
, struct file
*filp
, unsigned int cmd
, unsigned long data
)
964 struct ifx_ssc_port
*info
;
965 int line
, ret_val
= 0;
970 if ((inode
== (struct inode
*) 0) || (inode
== (struct inode
*) 1))
975 line
= MINOR (filp
->f_dentry
->d_inode
->i_rdev
);
978 if (line
< 0 || line
>= PORT_CNT
)
985 case IFX_SSC_STATS_READ
:
986 /* data must be a pointer to a struct ifx_ssc_statistics */
988 memcpy ((void *) data
, (void *) &info
->stats
,
989 sizeof (struct ifx_ssc_statistics
));
990 else if (copy_to_user ((void *) data
,
991 (void *) &info
->stats
,
992 sizeof (struct ifx_ssc_statistics
)))
995 case IFX_SSC_STATS_RESET
:
996 /* just resets the statistics counters */
997 memset ((void *) &info
->stats
, 0,
998 sizeof (struct ifx_ssc_statistics
));
1000 case IFX_SSC_BAUD_SET
:
1001 /* if the buffers are not empty then the port is */
1002 /* busy and we shouldn't change things on-the-fly! */
1003 if (!info
->txbuf
|| !info
->rxbuf
||
1004 (READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_STATE
)
1005 & IFX_SSC_STATE_BUSY
)) {
1011 flags
= *((unsigned long *) data
);
1012 else if (copy_from_user ((void *) &flags
,
1013 (void *) data
, sizeof (flags
))) {
1021 if (ifx_ssc_set_baud (info
, flags
) < 0) {
1027 case IFX_SSC_BAUD_GET
:
1029 *((unsigned int *) data
) = info
->baud
;
1030 else if (copy_to_user ((void *) data
,
1031 (void *) &info
->baud
,
1032 sizeof (unsigned long)))
1035 case IFX_SSC_RXTX_MODE_SET
:
1037 tmp
= *((unsigned long *) data
);
1038 else if (copy_from_user ((void *) &tmp
,
1039 (void *) data
, sizeof (tmp
))) {
1043 ret_val
= ifx_ssc_rxtx_mode_set (info
, tmp
);
1045 case IFX_SSC_RXTX_MODE_GET
:
1046 tmp
= READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_CON
) &
1047 (~(IFX_SSC_CON_RX_OFF
| IFX_SSC_CON_TX_OFF
));
1049 *((unsigned int *) data
) = tmp
;
1050 else if (copy_to_user ((void *) data
,
1051 (void *) &tmp
, sizeof (tmp
)))
1056 ifx_ssc_abort (info
);
1059 case IFX_SSC_GPO_OUT_SET
:
1061 tmp
= *((unsigned long *) data
);
1062 else if (copy_from_user ((void *) &tmp
,
1063 (void *) data
, sizeof (tmp
))) {
1067 if (tmp
> IFX_SSC_MAX_GPO_OUT
)
1070 WRITE_PERIPHERAL_REGISTER
1071 (1 << (tmp
+ IFX_SSC_WHBGPOSTAT_SETOUT0_POS
),
1072 info
->mapbase
+ IFX_SSC_WHBGPOSTAT
);
1074 case IFX_SSC_GPO_OUT_CLR
:
1076 tmp
= *((unsigned long *) data
);
1077 else if (copy_from_user ((void *) &tmp
,
1078 (void *) data
, sizeof (tmp
))) {
1082 if (tmp
> IFX_SSC_MAX_GPO_OUT
)
1085 WRITE_PERIPHERAL_REGISTER
1086 (1 << (tmp
+ IFX_SSC_WHBGPOSTAT_CLROUT0_POS
),
1087 info
->mapbase
+ IFX_SSC_WHBGPOSTAT
);
1090 case IFX_SSC_GPO_OUT_GET
:
1091 tmp
= READ_PERIPHERAL_REGISTER
1092 (info
->mapbase
+ IFX_SSC_GPOSTAT
);
1094 *((unsigned int *) data
) = tmp
;
1095 else if (copy_to_user ((void *) data
,
1096 (void *) &tmp
, sizeof (tmp
)))
1099 case IFX_SSC_FRM_STATUS_GET
:
1100 ifx_ssc_frm_status_get (info
);
1102 memcpy ((void *) data
, (void *) &info
->frm_status
,
1103 sizeof (struct ifx_ssc_frm_status
));
1104 else if (copy_to_user ((void *) data
,
1105 (void *) &info
->frm_status
,
1106 sizeof (struct ifx_ssc_frm_status
)))
1109 case IFX_SSC_FRM_CONTROL_GET
:
1110 ifx_ssc_frm_control_get (info
);
1112 memcpy ((void *) data
, (void *) &info
->frm_opts
,
1113 sizeof (struct ifx_ssc_frm_opts
));
1114 else if (copy_to_user ((void *) data
,
1115 (void *) &info
->frm_opts
,
1116 sizeof (struct ifx_ssc_frm_opts
)))
1119 case IFX_SSC_FRM_CONTROL_SET
:
1121 memcpy ((void *) &info
->frm_opts
, (void *) data
,
1122 sizeof (struct ifx_ssc_frm_opts
));
1123 else if (copy_to_user ((void *) &info
->frm_opts
,
1125 sizeof (struct ifx_ssc_frm_opts
))) {
1129 ret_val
= ifx_ssc_frm_control_set (info
);
1131 case IFX_SSC_HWOPTS_SET
:
1132 /* data must be a pointer to a struct ifx_ssc_hwopts */
1133 /* if the buffers are not empty then the port is */
1134 /* busy and we shouldn't change things on-the-fly! */
1135 if (!info
->txbuf
|| !info
->rxbuf
||
1136 (READ_PERIPHERAL_REGISTER (info
->mapbase
+ IFX_SSC_STATE
)
1137 & IFX_SSC_STATE_BUSY
)) {
1142 memcpy ((void *) &info
->opts
, (void *) data
,
1143 sizeof (struct ifx_ssc_hwopts
));
1144 else if (copy_from_user ((void *) &info
->opts
,
1146 sizeof (struct ifx_ssc_hwopts
))) {
1150 if (ifx_ssc_hwinit (info
) < 0) {
1154 case IFX_SSC_HWOPTS_GET
:
1155 /* data must be a pointer to a struct ifx_ssc_hwopts */
1157 memcpy ((void *) data
, (void *) &info
->opts
,
1158 sizeof (struct ifx_ssc_hwopts
));
1159 else if (copy_to_user ((void *) data
,
1160 (void *) &info
->opts
,
1161 sizeof (struct ifx_ssc_hwopts
)))
1165 ret_val
= -ENOIOCTLCMD
;
1170 EXPORT_SYMBOL(ifx_ssc_ioctl
);
1175 struct ifx_ssc_port
*info
;
1177 unsigned long flags
;
1181 nbytes
= PORT_CNT
* sizeof(struct ifx_ssc_port
);
1182 isp
= (struct ifx_ssc_port
*)kmalloc(nbytes
, GFP_KERNEL
);
1186 printk("%s: no memory for isp\n", __func__
);
1189 memset(isp
, 0, nbytes
);
1192 if ((i
= register_chrdev (maj
, "ssc", &ifx_ssc_fops
)) < 0)
1194 printk ("Unable to register major %d for the Infineon SSC\n", maj
);
1200 if ((i
= register_chrdev (maj
, "ssc", &ifx_ssc_fops
)) < 0)
1202 printk ("Unable to register major %d for the Infineon SSC\n", maj
);
1211 /* set default values in ifx_ssc_port */
1212 for (i
= 0; i
< PORT_CNT
; i
++) {
1215 /* default values for the HwOpts */
1216 info
->opts
.AbortErrDetect
= IFX_SSC_DEF_ABRT_ERR_DETECT
;
1217 info
->opts
.rxOvErrDetect
= IFX_SSC_DEF_RO_ERR_DETECT
;
1218 info
->opts
.rxUndErrDetect
= IFX_SSC_DEF_RU_ERR_DETECT
;
1219 info
->opts
.txOvErrDetect
= IFX_SSC_DEF_TO_ERR_DETECT
;
1220 info
->opts
.txUndErrDetect
= IFX_SSC_DEF_TU_ERR_DETECT
;
1221 info
->opts
.loopBack
= IFX_SSC_DEF_LOOP_BACK
;
1222 info
->opts
.echoMode
= IFX_SSC_DEF_ECHO_MODE
;
1223 info
->opts
.idleValue
= IFX_SSC_DEF_IDLE_DATA
;
1224 info
->opts
.clockPolarity
= IFX_SSC_DEF_CLOCK_POLARITY
;
1225 info
->opts
.clockPhase
= IFX_SSC_DEF_CLOCK_PHASE
;
1226 info
->opts
.headingControl
= IFX_SSC_DEF_HEADING_CONTROL
;
1227 info
->opts
.dataWidth
= IFX_SSC_DEF_DATA_WIDTH
;
1228 info
->opts
.modeRxTx
= IFX_SSC_DEF_MODE_RXTX
;
1229 info
->opts
.gpoCs
= IFX_SSC_DEF_GPO_CS
;
1230 info
->opts
.gpoInv
= IFX_SSC_DEF_GPO_INV
;
1231 info
->opts
.masterSelect
= IFX_SSC_DEF_MASTERSLAVE
;
1232 info
->baud
= IFX_SSC_DEF_BAUDRATE
;
1235 /* values specific to SSC1 */
1237 info
->mapbase
= IFXMIPS_SSC_BASE_ADDR
;
1238 info
->txirq
= IFXMIPS_SSC_TIR
;
1239 info
->rxirq
= IFXMIPS_SSC_RIR
;
1240 info
->errirq
= IFXMIPS_SSC_EIR
;
1243 WRITE_PERIPHERAL_REGISTER (IFX_SSC_DEF_RMC
<< IFX_CLC_RUN_DIVIDER_OFFSET
, info
->mapbase
+ IFX_SSC_CLC
);
1245 init_waitqueue_head (&info
->rwait
);
1247 local_irq_save (flags
);
1249 // init serial framing register
1250 WRITE_PERIPHERAL_REGISTER (IFX_SSC_DEF_SFCON
, info
->mapbase
+ IFX_SSC_SFCON
);
1252 ret_val
= request_irq(info
->txirq
, ifx_ssc_tx_int
, SA_INTERRUPT
, "ifx_ssc_tx", info
);
1255 printk("%s: unable to get irq %d\n", __func__
, info
->txirq
);
1256 local_irq_restore(flags
);
1260 ret_val
= request_irq(info
->rxirq
, ifx_ssc_rx_int
, SA_INTERRUPT
, "ifx_ssc_rx", info
);
1263 printk ("%s: unable to get irq %d\n", __func__
, info
->rxirq
);
1264 local_irq_restore (flags
);
1268 ret_val
= request_irq(info
->errirq
, ifx_ssc_err_int
, SA_INTERRUPT
,"ifx_ssc_err", info
);
1271 printk ("%s: unable to get irq %d\n", __func__
, info
->errirq
);
1272 local_irq_restore (flags
);
1275 WRITE_PERIPHERAL_REGISTER (IFX_SSC_DEF_IRNEN
, info
->mapbase
+ IFX_SSC_IRN_EN
);
1277 enable_irq(info
->txirq
);
1278 enable_irq(info
->rxirq
);
1279 enable_irq(info
->errirq
);
1281 local_irq_restore (flags
);
1284 for (i
= 0; i
< PORT_CNT
; i
++) {
1286 if (ifx_ssc_hwinit (info
) < 0)
1288 printk ("%s: hardware init failed for port %d\n", __func__
, i
);
1297 free_irq(isp
[0].txirq
, &isp
[0]);
1298 free_irq(isp
[0].rxirq
, &isp
[0]);
1299 free_irq(isp
[0].errirq
, &isp
[0]);
1306 ifx_ssc_cleanup_module (void)
1310 for (i
= 0; i
< PORT_CNT
; i
++) {
1311 WRITE_PERIPHERAL_REGISTER (IFX_SSC_WHBSTATE_CLR_ENABLE
, isp
[i
].mapbase
+ IFX_SSC_WHBSTATE
);
1312 free_irq(isp
[i
].txirq
, &isp
[i
]);
1313 free_irq(isp
[i
].rxirq
, &isp
[i
]);
1314 free_irq(isp
[i
].errirq
, &isp
[i
]);
1319 module_init(ifx_ssc_init
);
1320 module_exit(ifx_ssc_cleanup_module
);
1324 ifx_ssc_cs_low (u32 pin
)
1327 if ((ret
= ifx_ssc_ioctl ((struct inode
*) 0, NULL
, IFX_SSC_GPO_OUT_CLR
, (unsigned long) &pin
)))
1328 printk ("clear CS %d fails\n", pin
);
1333 EXPORT_SYMBOL(ifx_ssc_cs_low
);
1336 ifx_ssc_cs_high (u32 pin
)
1339 if ((ret
= ifx_ssc_ioctl((struct inode
*) 0, NULL
, IFX_SSC_GPO_OUT_SET
, (unsigned long) &pin
)))
1340 printk ("set CS %d fails\n", pin
);
1345 EXPORT_SYMBOL(ifx_ssc_cs_high
);
1348 ssc_session (char *tx_buf
, u32 tx_len
, char *rx_buf
, u32 rx_len
)
1352 char *ssc_tx_buf
= NULL
;
1353 char *ssc_rx_buf
= NULL
;
1357 if (tx_buf
== NULL
&& tx_len
== 0 && rx_buf
== NULL
&& rx_len
== 0) {
1358 printk ("invalid parameters\n");
1360 goto ssc_session_exit
;
1362 else if (tx_buf
== NULL
|| tx_len
== 0) {
1363 if (rx_buf
!= NULL
&& rx_len
!= 0) {
1364 mode
= IFX_SSC_MODE_RX
;
1367 printk ("invalid parameters\n");
1369 goto ssc_session_exit
;
1372 else if (rx_buf
== NULL
|| rx_len
== 0) {
1373 if (tx_buf
!= NULL
&& tx_len
!= 0) {
1374 mode
= IFX_SSC_MODE_TX
;
1377 printk ("invalid parameters\n");
1379 goto ssc_session_exit
;
1383 mode
= IFX_SSC_MODE_RXTX
;
1386 if (mode
== IFX_SSC_MODE_RXTX
) {
1387 eff_size
= tx_len
+ rx_len
;
1389 else if (mode
== IFX_SSC_MODE_RX
) {
1396 //4 bytes alignment, required by driver
1397 /* change by TaiCheng */
1401 (char *) kmalloc (sizeof (char) *
1402 ((eff_size
+ 3) & (~3)),
1405 (char *) kmalloc (sizeof (char) *
1406 ((eff_size
+ 3) & (~3)),
1411 (char *) kmalloc (sizeof (char) *
1412 ((eff_size
+ 3) & (~3)),
1415 (char *) kmalloc (sizeof (char) *
1416 ((eff_size
+ 3) & (~3)),
1419 if (ssc_tx_buf
== NULL
|| ssc_rx_buf
== NULL
) {
1420 printk ("no memory for size of %d\n", eff_size
);
1422 goto ssc_session_exit
;
1424 memset ((void *) ssc_tx_buf
, 0, eff_size
);
1425 memset ((void *) ssc_rx_buf
, 0, eff_size
);
1428 memcpy (ssc_tx_buf
, tx_buf
, tx_len
);
1431 ret
= ifx_ssc_kwrite (0, ssc_tx_buf
, eff_size
);
1434 ssc_tx_buf
= NULL
; //should be freed by ifx_ssc_kwrite
1437 if (ret
!= eff_size
) {
1438 printk ("ifx_ssc_write return %d\n", ret
);
1439 goto ssc_session_exit
;
1441 ret
= ifx_ssc_kread (0, ssc_rx_buf
, eff_size
);
1442 if (ret
!= eff_size
) {
1443 printk ("ifx_ssc_read return %d\n", ret
);
1444 goto ssc_session_exit
;
1447 memcpy (rx_buf
, ssc_rx_buf
+ tx_len
, rx_len
);
1449 if (mode
== IFX_SSC_MODE_TX
) {
1457 if (ssc_tx_buf
!= NULL
)
1459 if (ssc_rx_buf
!= NULL
)
1463 printk ("ssc session fails\n");
1469 ifx_ssc_txrx (char *tx_buf
, u32 tx_len
, char *rx_buf
, u32 rx_len
)
1471 return ssc_session(tx_buf
, tx_len
, rx_buf
, rx_len
);
1473 EXPORT_SYMBOL(ifx_ssc_txrx
);
1476 ifx_ssc_tx (char *tx_buf
, u32 tx_len
)
1478 return ssc_session(tx_buf
, tx_len
, NULL
, 0);
1480 EXPORT_SYMBOL(ifx_ssc_tx
);
1483 ifx_ssc_rx (char *rx_buf
, u32 rx_len
)
1485 return ssc_session(NULL
, 0, rx_buf
, rx_len
);
1487 EXPORT_SYMBOL(ifx_ssc_rx
);
1489 MODULE_LICENSE("GPL");
1490 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
1491 MODULE_DESCRIPTION("ifxmips ssc driver");