aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Fulghum <paulkf@microgate.com>2006-03-28 04:56:15 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-28 12:16:02 -0500
commit0080b7aae88c75e2a6b38dfcb228b0f239e18e3c (patch)
tree445aadcb5f4e6271d9dfc6a35395a0a3a57716c6
parent86a34147d1f1c94e94500e63e83f9fa42548a088 (diff)
[PATCH] synclink_gt add gpio feature
Add driver support for general purpose I/O feature of the Synclink GT adapters. Signed-off-by: Paul Fulghum <paulkf@micrgate.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/char/synclink_gt.c246
-rw-r--r--include/linux/synclink.h11
2 files changed, 252 insertions, 5 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 738ec2f4e563..8818042bad7c 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: synclink_gt.c,v 4.22 2006/01/09 20:16:06 paulkf Exp $ 2 * $Id: synclink_gt.c,v 4.25 2006/02/06 21:20:33 paulkf Exp $
3 * 3 *
4 * Device driver for Microgate SyncLink GT serial adapters. 4 * Device driver for Microgate SyncLink GT serial adapters.
5 * 5 *
@@ -92,7 +92,7 @@
92 * module identification 92 * module identification
93 */ 93 */
94static char *driver_name = "SyncLink GT"; 94static char *driver_name = "SyncLink GT";
95static char *driver_version = "$Revision: 4.22 $"; 95static char *driver_version = "$Revision: 4.25 $";
96static char *tty_driver_name = "synclink_gt"; 96static char *tty_driver_name = "synclink_gt";
97static char *tty_dev_prefix = "ttySLG"; 97static char *tty_dev_prefix = "ttySLG";
98MODULE_LICENSE("GPL"); 98MODULE_LICENSE("GPL");
@@ -188,6 +188,20 @@ static void hdlcdev_exit(struct slgt_info *info);
188#define SLGT_REG_SIZE 256 188#define SLGT_REG_SIZE 256
189 189
190/* 190/*
191 * conditional wait facility
192 */
193struct cond_wait {
194 struct cond_wait *next;
195 wait_queue_head_t q;
196 wait_queue_t wait;
197 unsigned int data;
198};
199static void init_cond_wait(struct cond_wait *w, unsigned int data);
200static void add_cond_wait(struct cond_wait **head, struct cond_wait *w);
201static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w);
202static void flush_cond_wait(struct cond_wait **head);
203
204/*
191 * DMA buffer descriptor and access macros 205 * DMA buffer descriptor and access macros
192 */ 206 */
193struct slgt_desc 207struct slgt_desc
@@ -269,6 +283,9 @@ struct slgt_info {
269 struct timer_list tx_timer; 283 struct timer_list tx_timer;
270 struct timer_list rx_timer; 284 struct timer_list rx_timer;
271 285
286 unsigned int gpio_present;
287 struct cond_wait *gpio_wait_q;
288
272 spinlock_t lock; /* spinlock for synchronizing with ISR */ 289 spinlock_t lock; /* spinlock for synchronizing with ISR */
273 290
274 struct work_struct task; 291 struct work_struct task;
@@ -379,6 +396,11 @@ static MGSL_PARAMS default_params = {
379#define MASK_OVERRUN BIT4 396#define MASK_OVERRUN BIT4
380 397
381#define GSR 0x00 /* global status */ 398#define GSR 0x00 /* global status */
399#define JCR 0x04 /* JTAG control */
400#define IODR 0x08 /* GPIO direction */
401#define IOER 0x0c /* GPIO interrupt enable */
402#define IOVR 0x10 /* GPIO value */
403#define IOSR 0x14 /* GPIO interrupt status */
382#define TDR 0x80 /* tx data */ 404#define TDR 0x80 /* tx data */
383#define RDR 0x80 /* rx data */ 405#define RDR 0x80 /* rx data */
384#define TCR 0x82 /* tx control */ 406#define TCR 0x82 /* tx control */
@@ -503,6 +525,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
503static void set_break(struct tty_struct *tty, int break_state); 525static void set_break(struct tty_struct *tty, int break_state);
504static int get_interface(struct slgt_info *info, int __user *if_mode); 526static int get_interface(struct slgt_info *info, int __user *if_mode);
505static int set_interface(struct slgt_info *info, int if_mode); 527static int set_interface(struct slgt_info *info, int if_mode);
528static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
529static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
530static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
506 531
507/* 532/*
508 * driver functions 533 * driver functions
@@ -1112,6 +1137,12 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1112 return get_interface(info, argp); 1137 return get_interface(info, argp);
1113 case MGSL_IOCSIF: 1138 case MGSL_IOCSIF:
1114 return set_interface(info,(int)arg); 1139 return set_interface(info,(int)arg);
1140 case MGSL_IOCSGPIO:
1141 return set_gpio(info, argp);
1142 case MGSL_IOCGGPIO:
1143 return get_gpio(info, argp);
1144 case MGSL_IOCWAITGPIO:
1145 return wait_gpio(info, argp);
1115 case TIOCGICOUNT: 1146 case TIOCGICOUNT:
1116 spin_lock_irqsave(&info->lock,flags); 1147 spin_lock_irqsave(&info->lock,flags);
1117 cnow = info->icount; 1148 cnow = info->icount;
@@ -2158,6 +2189,24 @@ static void isr_txeom(struct slgt_info *info, unsigned short status)
2158 } 2189 }
2159} 2190}
2160 2191
2192static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int state)
2193{
2194 struct cond_wait *w, *prev;
2195
2196 /* wake processes waiting for specific transitions */
2197 for (w = info->gpio_wait_q, prev = NULL ; w != NULL ; w = w->next) {
2198 if (w->data & changed) {
2199 w->data = state;
2200 wake_up_interruptible(&w->q);
2201 if (prev != NULL)
2202 prev->next = w->next;
2203 else
2204 info->gpio_wait_q = w->next;
2205 } else
2206 prev = w;
2207 }
2208}
2209
2161/* interrupt service routine 2210/* interrupt service routine
2162 * 2211 *
2163 * irq interrupt number 2212 * irq interrupt number
@@ -2193,6 +2242,22 @@ static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs)
2193 } 2242 }
2194 } 2243 }
2195 2244
2245 if (info->gpio_present) {
2246 unsigned int state;
2247 unsigned int changed;
2248 while ((changed = rd_reg32(info, IOSR)) != 0) {
2249 DBGISR(("%s iosr=%08x\n", info->device_name, changed));
2250 /* read latched state of GPIO signals */
2251 state = rd_reg32(info, IOVR);
2252 /* clear pending GPIO interrupt bits */
2253 wr_reg32(info, IOSR, changed);
2254 for (i=0 ; i < info->port_count ; i++) {
2255 if (info->port_array[i] != NULL)
2256 isr_gpio(info->port_array[i], changed, state);
2257 }
2258 }
2259 }
2260
2196 for(i=0; i < info->port_count ; i++) { 2261 for(i=0; i < info->port_count ; i++) {
2197 struct slgt_info *port = info->port_array[i]; 2262 struct slgt_info *port = info->port_array[i];
2198 2263
@@ -2276,6 +2341,8 @@ static void shutdown(struct slgt_info *info)
2276 set_signals(info); 2341 set_signals(info);
2277 } 2342 }
2278 2343
2344 flush_cond_wait(&info->gpio_wait_q);
2345
2279 spin_unlock_irqrestore(&info->lock,flags); 2346 spin_unlock_irqrestore(&info->lock,flags);
2280 2347
2281 if (info->tty) 2348 if (info->tty)
@@ -2650,6 +2717,175 @@ static int set_interface(struct slgt_info *info, int if_mode)
2650 return 0; 2717 return 0;
2651} 2718}
2652 2719
2720/*
2721 * set general purpose IO pin state and direction
2722 *
2723 * user_gpio fields:
2724 * state each bit indicates a pin state
2725 * smask set bit indicates pin state to set
2726 * dir each bit indicates a pin direction (0=input, 1=output)
2727 * dmask set bit indicates pin direction to set
2728 */
2729static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
2730{
2731 unsigned long flags;
2732 struct gpio_desc gpio;
2733 __u32 data;
2734
2735 if (!info->gpio_present)
2736 return -EINVAL;
2737 if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
2738 return -EFAULT;
2739 DBGINFO(("%s set_gpio state=%08x smask=%08x dir=%08x dmask=%08x\n",
2740 info->device_name, gpio.state, gpio.smask,
2741 gpio.dir, gpio.dmask));
2742
2743 spin_lock_irqsave(&info->lock,flags);
2744 if (gpio.dmask) {
2745 data = rd_reg32(info, IODR);
2746 data |= gpio.dmask & gpio.dir;
2747 data &= ~(gpio.dmask & ~gpio.dir);
2748 wr_reg32(info, IODR, data);
2749 }
2750 if (gpio.smask) {
2751 data = rd_reg32(info, IOVR);
2752 data |= gpio.smask & gpio.state;
2753 data &= ~(gpio.smask & ~gpio.state);
2754 wr_reg32(info, IOVR, data);
2755 }
2756 spin_unlock_irqrestore(&info->lock,flags);
2757
2758 return 0;
2759}
2760
2761/*
2762 * get general purpose IO pin state and direction
2763 */
2764static int get_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
2765{
2766 struct gpio_desc gpio;
2767 if (!info->gpio_present)
2768 return -EINVAL;
2769 gpio.state = rd_reg32(info, IOVR);
2770 gpio.smask = 0xffffffff;
2771 gpio.dir = rd_reg32(info, IODR);
2772 gpio.dmask = 0xffffffff;
2773 if (copy_to_user(user_gpio, &gpio, sizeof(gpio)))
2774 return -EFAULT;
2775 DBGINFO(("%s get_gpio state=%08x dir=%08x\n",
2776 info->device_name, gpio.state, gpio.dir));
2777 return 0;
2778}
2779
2780/*
2781 * conditional wait facility
2782 */
2783static void init_cond_wait(struct cond_wait *w, unsigned int data)
2784{
2785 init_waitqueue_head(&w->q);
2786 init_waitqueue_entry(&w->wait, current);
2787 w->data = data;
2788}
2789
2790static void add_cond_wait(struct cond_wait **head, struct cond_wait *w)
2791{
2792 set_current_state(TASK_INTERRUPTIBLE);
2793 add_wait_queue(&w->q, &w->wait);
2794 w->next = *head;
2795 *head = w;
2796}
2797
2798static void remove_cond_wait(struct cond_wait **head, struct cond_wait *cw)
2799{
2800 struct cond_wait *w, *prev;
2801 remove_wait_queue(&cw->q, &cw->wait);
2802 set_current_state(TASK_RUNNING);
2803 for (w = *head, prev = NULL ; w != NULL ; prev = w, w = w->next) {
2804 if (w == cw) {
2805 if (prev != NULL)
2806 prev->next = w->next;
2807 else
2808 *head = w->next;
2809 break;
2810 }
2811 }
2812}
2813
2814static void flush_cond_wait(struct cond_wait **head)
2815{
2816 while (*head != NULL) {
2817 wake_up_interruptible(&(*head)->q);
2818 *head = (*head)->next;
2819 }
2820}
2821
2822/*
2823 * wait for general purpose I/O pin(s) to enter specified state
2824 *
2825 * user_gpio fields:
2826 * state - bit indicates target pin state
2827 * smask - set bit indicates watched pin
2828 *
2829 * The wait ends when at least one watched pin enters the specified
2830 * state. When 0 (no error) is returned, user_gpio->state is set to the
2831 * state of all GPIO pins when the wait ends.
2832 *
2833 * Note: Each pin may be a dedicated input, dedicated output, or
2834 * configurable input/output. The number and configuration of pins
2835 * varies with the specific adapter model. Only input pins (dedicated
2836 * or configured) can be monitored with this function.
2837 */
2838static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
2839{
2840 unsigned long flags;
2841 int rc = 0;
2842 struct gpio_desc gpio;
2843 struct cond_wait wait;
2844 u32 state;
2845
2846 if (!info->gpio_present)
2847 return -EINVAL;
2848 if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
2849 return -EFAULT;
2850 DBGINFO(("%s wait_gpio() state=%08x smask=%08x\n",
2851 info->device_name, gpio.state, gpio.smask));
2852 /* ignore output pins identified by set IODR bit */
2853 if ((gpio.smask &= ~rd_reg32(info, IODR)) == 0)
2854 return -EINVAL;
2855 init_cond_wait(&wait, gpio.smask);
2856
2857 spin_lock_irqsave(&info->lock, flags);
2858 /* enable interrupts for watched pins */
2859 wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask);
2860 /* get current pin states */
2861 state = rd_reg32(info, IOVR);
2862
2863 if (gpio.smask & ~(state ^ gpio.state)) {
2864 /* already in target state */
2865 gpio.state = state;
2866 } else {
2867 /* wait for target state */
2868 add_cond_wait(&info->gpio_wait_q, &wait);
2869 spin_unlock_irqrestore(&info->lock, flags);
2870 schedule();
2871 if (signal_pending(current))
2872 rc = -ERESTARTSYS;
2873 else
2874 gpio.state = wait.data;
2875 spin_lock_irqsave(&info->lock, flags);
2876 remove_cond_wait(&info->gpio_wait_q, &wait);
2877 }
2878
2879 /* disable all GPIO interrupts if no waiting processes */
2880 if (info->gpio_wait_q == NULL)
2881 wr_reg32(info, IOER, 0);
2882 spin_unlock_irqrestore(&info->lock,flags);
2883
2884 if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio)))
2885 rc = -EFAULT;
2886 return rc;
2887}
2888
2653static int modem_input_wait(struct slgt_info *info,int arg) 2889static int modem_input_wait(struct slgt_info *info,int arg)
2654{ 2890{
2655 unsigned long flags; 2891 unsigned long flags;
@@ -3166,8 +3402,10 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
3166 } else { 3402 } else {
3167 port_array[0]->irq_requested = 1; 3403 port_array[0]->irq_requested = 1;
3168 adapter_test(port_array[0]); 3404 adapter_test(port_array[0]);
3169 for (i=1 ; i < port_count ; i++) 3405 for (i=1 ; i < port_count ; i++) {
3170 port_array[i]->init_error = port_array[0]->init_error; 3406 port_array[i]->init_error = port_array[0]->init_error;
3407 port_array[i]->gpio_present = port_array[0]->gpio_present;
3408 }
3171 } 3409 }
3172 } 3410 }
3173} 3411}
@@ -4301,7 +4539,7 @@ static int register_test(struct slgt_info *info)
4301 break; 4539 break;
4302 } 4540 }
4303 } 4541 }
4304 4542 info->gpio_present = (rd_reg32(info, JCR) & BIT5) ? 1 : 0;
4305 info->init_error = rc ? 0 : DiagStatus_AddressFailure; 4543 info->init_error = rc ? 0 : DiagStatus_AddressFailure;
4306 return rc; 4544 return rc;
4307} 4545}
diff --git a/include/linux/synclink.h b/include/linux/synclink.h
index 1b7cd8d1a71b..2993302f7923 100644
--- a/include/linux/synclink.h
+++ b/include/linux/synclink.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * SyncLink Multiprotocol Serial Adapter Driver 2 * SyncLink Multiprotocol Serial Adapter Driver
3 * 3 *
4 * $Id: synclink.h,v 3.10 2005/11/08 19:50:54 paulkf Exp $ 4 * $Id: synclink.h,v 3.11 2006/02/06 21:20:29 paulkf Exp $
5 * 5 *
6 * Copyright (C) 1998-2000 by Microgate Corporation 6 * Copyright (C) 1998-2000 by Microgate Corporation
7 * 7 *
@@ -221,6 +221,12 @@ struct mgsl_icount {
221 __u32 rxidle; 221 __u32 rxidle;
222}; 222};
223 223
224struct gpio_desc {
225 __u32 state;
226 __u32 smask;
227 __u32 dir;
228 __u32 dmask;
229};
224 230
225#define DEBUG_LEVEL_DATA 1 231#define DEBUG_LEVEL_DATA 1
226#define DEBUG_LEVEL_ERROR 2 232#define DEBUG_LEVEL_ERROR 2
@@ -276,5 +282,8 @@ struct mgsl_icount {
276#define MGSL_IOCLOOPTXDONE _IO(MGSL_MAGIC_IOC,9) 282#define MGSL_IOCLOOPTXDONE _IO(MGSL_MAGIC_IOC,9)
277#define MGSL_IOCSIF _IO(MGSL_MAGIC_IOC,10) 283#define MGSL_IOCSIF _IO(MGSL_MAGIC_IOC,10)
278#define MGSL_IOCGIF _IO(MGSL_MAGIC_IOC,11) 284#define MGSL_IOCGIF _IO(MGSL_MAGIC_IOC,11)
285#define MGSL_IOCSGPIO _IOW(MGSL_MAGIC_IOC,16,struct gpio_desc)
286#define MGSL_IOCGGPIO _IOR(MGSL_MAGIC_IOC,17,struct gpio_desc)
287#define MGSL_IOCWAITGPIO _IOWR(MGSL_MAGIC_IOC,18,struct gpio_desc)
279 288
280#endif /* _SYNCLINK_H_ */ 289#endif /* _SYNCLINK_H_ */