Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.22 240 lines 6.4 kB view raw
1/********************************************************************* 2 * 3 * 4 * Filename: mcp2120.c 5 * Version: 1.0 6 * Description: Implementation for the MCP2120 (Microchip) 7 * Status: Experimental. 8 * Author: Felix Tang (tangf@eyetap.org) 9 * Created at: Sun Mar 31 19:32:12 EST 2002 10 * Based on code by: Dag Brattli <dagb@cs.uit.no> 11 * 12 * Copyright (c) 2002 Felix Tang, All Rights Reserved. 13 * 14 * This program is free software; you can redistribute it and/or 15 * modify it under the terms of the GNU General Public License as 16 * published by the Free Software Foundation; either version 2 of 17 * the License, or (at your option) any later version. 18 * 19 ********************************************************************/ 20 21#include <linux/module.h> 22#include <linux/delay.h> 23#include <linux/tty.h> 24#include <linux/init.h> 25 26#include <net/irda/irda.h> 27#include <net/irda/irda_device.h> 28 29static int mcp2120_reset(struct irda_task *task); 30static void mcp2120_open(dongle_t *self, struct qos_info *qos); 31static void mcp2120_close(dongle_t *self); 32static int mcp2120_change_speed(struct irda_task *task); 33 34#define MCP2120_9600 0x87 35#define MCP2120_19200 0x8B 36#define MCP2120_38400 0x85 37#define MCP2120_57600 0x83 38#define MCP2120_115200 0x81 39 40#define MCP2120_COMMIT 0x11 41 42static struct dongle_reg dongle = { 43 .type = IRDA_MCP2120_DONGLE, 44 .open = mcp2120_open, 45 .close = mcp2120_close, 46 .reset = mcp2120_reset, 47 .change_speed = mcp2120_change_speed, 48 .owner = THIS_MODULE, 49}; 50 51static int __init mcp2120_init(void) 52{ 53 return irda_device_register_dongle(&dongle); 54} 55 56static void __exit mcp2120_cleanup(void) 57{ 58 irda_device_unregister_dongle(&dongle); 59} 60 61static void mcp2120_open(dongle_t *self, struct qos_info *qos) 62{ 63 qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; 64 qos->min_turn_time.bits = 0x01; 65} 66 67static void mcp2120_close(dongle_t *self) 68{ 69 /* Power off dongle */ 70 /* reset and inhibit mcp2120 */ 71 self->set_dtr_rts(self->dev, TRUE, TRUE); 72 //self->set_dtr_rts(self->dev, FALSE, FALSE); 73} 74 75/* 76 * Function mcp2120_change_speed (dev, speed) 77 * 78 * Set the speed for the MCP2120. 79 * 80 */ 81static int mcp2120_change_speed(struct irda_task *task) 82{ 83 dongle_t *self = (dongle_t *) task->instance; 84 __u32 speed = (__u32) task->param; 85 __u8 control[2]; 86 int ret = 0; 87 88 self->speed_task = task; 89 90 switch (task->state) { 91 case IRDA_TASK_INIT: 92 /* Need to reset the dongle and go to 9600 bps before 93 programming */ 94 //printk("Dmcp2120_change_speed irda_task_init\n"); 95 if (irda_task_execute(self, mcp2120_reset, NULL, task, 96 (void *) speed)) 97 { 98 /* Dongle need more time to reset */ 99 irda_task_next_state(task, IRDA_TASK_CHILD_WAIT); 100 101 /* Give reset 1 sec to finish */ 102 ret = msecs_to_jiffies(1000); 103 } 104 break; 105 case IRDA_TASK_CHILD_WAIT: 106 IRDA_WARNING("%s(), resetting dongle timed out!\n", 107 __FUNCTION__); 108 ret = -1; 109 break; 110 case IRDA_TASK_CHILD_DONE: 111 /* Set DTR to enter command mode */ 112 self->set_dtr_rts(self->dev, TRUE, FALSE); 113 udelay(500); 114 115 switch (speed) { 116 case 9600: 117 default: 118 control[0] = MCP2120_9600; 119 //printk("mcp2120 9600\n"); 120 break; 121 case 19200: 122 control[0] = MCP2120_19200; 123 //printk("mcp2120 19200\n"); 124 break; 125 case 34800: 126 control[0] = MCP2120_38400; 127 //printk("mcp2120 38400\n"); 128 break; 129 case 57600: 130 control[0] = MCP2120_57600; 131 //printk("mcp2120 57600\n"); 132 break; 133 case 115200: 134 control[0] = MCP2120_115200; 135 //printk("mcp2120 115200\n"); 136 break; 137 } 138 control[1] = MCP2120_COMMIT; 139 140 /* Write control bytes */ 141 self->write(self->dev, control, 2); 142 143 irda_task_next_state(task, IRDA_TASK_WAIT); 144 ret = msecs_to_jiffies(100); 145 //printk("mcp2120_change_speed irda_child_done\n"); 146 break; 147 case IRDA_TASK_WAIT: 148 /* Go back to normal mode */ 149 self->set_dtr_rts(self->dev, FALSE, FALSE); 150 irda_task_next_state(task, IRDA_TASK_DONE); 151 self->speed_task = NULL; 152 //printk("mcp2120_change_speed irda_task_wait\n"); 153 break; 154 default: 155 IRDA_ERROR("%s(), unknown state %d\n", 156 __FUNCTION__, task->state); 157 irda_task_next_state(task, IRDA_TASK_DONE); 158 self->speed_task = NULL; 159 ret = -1; 160 break; 161 } 162 return ret; 163} 164 165/* 166 * Function mcp2120_reset (driver) 167 * 168 * This function resets the mcp2120 dongle. 169 * 170 * Info: -set RTS to reset mcp2120 171 * -set DTR to set mcp2120 software command mode 172 * -mcp2120 defaults to 9600 baud after reset 173 * 174 * Algorithm: 175 * 0. Set RTS to reset mcp2120. 176 * 1. Clear RTS and wait for device reset timer of 30 ms (max). 177 * 178 */ 179 180 181static int mcp2120_reset(struct irda_task *task) 182{ 183 dongle_t *self = (dongle_t *) task->instance; 184 int ret = 0; 185 186 self->reset_task = task; 187 188 switch (task->state) { 189 case IRDA_TASK_INIT: 190 //printk("mcp2120_reset irda_task_init\n"); 191 /* Reset dongle by setting RTS*/ 192 self->set_dtr_rts(self->dev, TRUE, TRUE); 193 irda_task_next_state(task, IRDA_TASK_WAIT1); 194 ret = msecs_to_jiffies(50); 195 break; 196 case IRDA_TASK_WAIT1: 197 //printk("mcp2120_reset irda_task_wait1\n"); 198 /* clear RTS and wait for at least 30 ms. */ 199 self->set_dtr_rts(self->dev, FALSE, FALSE); 200 irda_task_next_state(task, IRDA_TASK_WAIT2); 201 ret = msecs_to_jiffies(50); 202 break; 203 case IRDA_TASK_WAIT2: 204 //printk("mcp2120_reset irda_task_wait2\n"); 205 /* Go back to normal mode */ 206 self->set_dtr_rts(self->dev, FALSE, FALSE); 207 irda_task_next_state(task, IRDA_TASK_DONE); 208 self->reset_task = NULL; 209 break; 210 default: 211 IRDA_ERROR("%s(), unknown state %d\n", 212 __FUNCTION__, task->state); 213 irda_task_next_state(task, IRDA_TASK_DONE); 214 self->reset_task = NULL; 215 ret = -1; 216 break; 217 } 218 return ret; 219} 220 221MODULE_AUTHOR("Felix Tang <tangf@eyetap.org>"); 222MODULE_DESCRIPTION("Microchip MCP2120"); 223MODULE_LICENSE("GPL"); 224MODULE_ALIAS("irda-dongle-9"); /* IRDA_MCP2120_DONGLE */ 225 226/* 227 * Function init_module (void) 228 * 229 * Initialize MCP2120 module 230 * 231 */ 232module_init(mcp2120_init); 233 234/* 235 * Function cleanup_module (void) 236 * 237 * Cleanup MCP2120 module 238 * 239 */ 240module_exit(mcp2120_cleanup);