davicom.c revision 8b7c1664405a1262bb78e80011ec10aa6b79df81
100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming/* 200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * drivers/net/phy/davicom.c 300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Driver for Davicom PHYs 500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Author: Andy Fleming 700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Copyright (c) 2004 Freescale Semiconductor, Inc. 900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 1000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * This program is free software; you can redistribute it and/or modify it 1100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * under the terms of the GNU General Public License as published by the 1200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Free Software Foundation; either version 2 of the License, or (at your 1300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * option) any later version. 1400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 1500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming */ 1600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/kernel.h> 1700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/string.h> 1800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/errno.h> 1900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/unistd.h> 2000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/slab.h> 2100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/interrupt.h> 2200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/init.h> 2300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/delay.h> 2400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/netdevice.h> 2500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/etherdevice.h> 2600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/skbuff.h> 2700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/spinlock.h> 2800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/mm.h> 2900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/module.h> 3000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/mii.h> 3100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/ethtool.h> 3200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/phy.h> 3300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 3400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <asm/io.h> 3500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <asm/irq.h> 3600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <asm/uaccess.h> 3700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 3800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_SCR 0x10 3900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_SCR_INIT 0x0610 408b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo#define MII_DM9161_SCR_RMII 0x0100 4100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 4200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming/* DM9161 Interrupt Register */ 4300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_INTR 0x15 4400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_INTR_PEND 0x8000 4500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_INTR_DPLX_MASK 0x0800 4600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_INTR_SPD_MASK 0x0400 4700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_INTR_LINK_MASK 0x0200 4800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_INTR_MASK 0x0100 4900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_INTR_DPLX_CHANGE 0x0010 5000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_INTR_SPD_CHANGE 0x0008 5100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_INTR_LINK_CHANGE 0x0004 5200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_INTR_INIT 0x0000 5300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_INTR_STOP \ 5400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \ 5500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK) 5600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 5700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming/* DM9161 10BT Configuration/Status */ 5800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_10BTCSR 0x12 5900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define MII_DM9161_10BTCSR_INIT 0x7800 6000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 6100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy FlemingMODULE_DESCRIPTION("Davicom PHY driver"); 6200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy FlemingMODULE_AUTHOR("Andy Fleming"); 6300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy FlemingMODULE_LICENSE("GPL"); 6400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 6500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 6600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#define DM9161_DELAY 1 6700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingstatic int dm9161_config_intr(struct phy_device *phydev) 6800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 6900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int temp; 7000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 7100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming temp = phy_read(phydev, MII_DM9161_INTR); 7200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 7300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (temp < 0) 7400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return temp; 7500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 7600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if(PHY_INTERRUPT_ENABLED == phydev->interrupts ) 7700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming temp &= ~(MII_DM9161_INTR_STOP); 7800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming else 7900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming temp |= MII_DM9161_INTR_STOP; 8000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 8100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming temp = phy_write(phydev, MII_DM9161_INTR, temp); 8200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 8300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return temp; 8400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 8500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 8600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingstatic int dm9161_config_aneg(struct phy_device *phydev) 8700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 8800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int err; 8900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 9000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Isolate the PHY */ 9100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE); 9200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 9300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err < 0) 9400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return err; 9500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 9600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Configure the new settings */ 9700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = genphy_config_aneg(phydev); 9800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 9900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err < 0) 10000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return err; 10100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 10200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return 0; 10300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 10400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 10500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingstatic int dm9161_config_init(struct phy_device *phydev) 10600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 1078b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo int err, temp; 10800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 10900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Isolate the PHY */ 11000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE); 11100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 11200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err < 0) 11300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return err; 11400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 1158b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo switch (phydev->interface) { 1168b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo case PHY_INTERFACE_MODE_MII: 1178b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo temp = MII_DM9161_SCR_INIT; 1188b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo break; 1198b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo case PHY_INTERFACE_MODE_RMII: 1208b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo temp = MII_DM9161_SCR_INIT | MII_DM9161_SCR_RMII; 1218b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo break; 1228b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo default: 1238b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo return -EINVAL; 1248b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo } 12500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 1268b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo /* Do not bypass the scrambler/descrambler */ 1278b7c1664405a1262bb78e80011ec10aa6b79df81frederic Rodo err = phy_write(phydev, MII_DM9161_SCR, temp); 12800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err < 0) 12900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return err; 13000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 13100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Clear 10BTCSR to default */ 13200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_write(phydev, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT); 13300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 13400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err < 0) 13500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return err; 13600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 13700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Reconnect the PHY, and enable Autonegotiation */ 13800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_write(phydev, MII_BMCR, BMCR_ANENABLE); 13900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 14000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err < 0) 14100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return err; 14200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 14300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return 0; 14400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 14500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 14600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingstatic int dm9161_ack_interrupt(struct phy_device *phydev) 14700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 14800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int err = phy_read(phydev, MII_DM9161_INTR); 14900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 15000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return (err < 0) ? err : 0; 15100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 15200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 15312414db11da8789d9a6b549c4899250f6e116630Kim Phillipsstatic struct phy_driver dm9161e_driver = { 15400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .phy_id = 0x0181b880, 15500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .name = "Davicom DM9161E", 15600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .phy_id_mask = 0x0ffffff0, 15700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .features = PHY_BASIC_FEATURES, 15800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .config_init = dm9161_config_init, 15900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .config_aneg = dm9161_config_aneg, 16000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .read_status = genphy_read_status, 16112414db11da8789d9a6b549c4899250f6e116630Kim Phillips .driver = { .owner = THIS_MODULE,}, 16212414db11da8789d9a6b549c4899250f6e116630Kim Phillips}; 16312414db11da8789d9a6b549c4899250f6e116630Kim Phillips 16412414db11da8789d9a6b549c4899250f6e116630Kim Phillipsstatic struct phy_driver dm9161a_driver = { 16512414db11da8789d9a6b549c4899250f6e116630Kim Phillips .phy_id = 0x0181b8a0, 16612414db11da8789d9a6b549c4899250f6e116630Kim Phillips .name = "Davicom DM9161A", 16712414db11da8789d9a6b549c4899250f6e116630Kim Phillips .phy_id_mask = 0x0ffffff0, 16812414db11da8789d9a6b549c4899250f6e116630Kim Phillips .features = PHY_BASIC_FEATURES, 16912414db11da8789d9a6b549c4899250f6e116630Kim Phillips .config_init = dm9161_config_init, 17012414db11da8789d9a6b549c4899250f6e116630Kim Phillips .config_aneg = dm9161_config_aneg, 17112414db11da8789d9a6b549c4899250f6e116630Kim Phillips .read_status = genphy_read_status, 17212414db11da8789d9a6b549c4899250f6e116630Kim Phillips .driver = { .owner = THIS_MODULE,}, 17300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming}; 17400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 17500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingstatic struct phy_driver dm9131_driver = { 17600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .phy_id = 0x00181b80, 17700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .name = "Davicom DM9131", 17800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .phy_id_mask = 0x0ffffff0, 17900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .features = PHY_BASIC_FEATURES, 18000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .flags = PHY_HAS_INTERRUPT, 18100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .config_aneg = genphy_config_aneg, 18200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .read_status = genphy_read_status, 18300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .ack_interrupt = dm9161_ack_interrupt, 18400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .config_intr = dm9161_config_intr, 18512414db11da8789d9a6b549c4899250f6e116630Kim Phillips .driver = { .owner = THIS_MODULE,}, 18600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming}; 18700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 18800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingstatic int __init davicom_init(void) 18900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 19000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int ret; 19100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 19212414db11da8789d9a6b549c4899250f6e116630Kim Phillips ret = phy_driver_register(&dm9161e_driver); 19300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (ret) 19400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming goto err1; 19500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 19612414db11da8789d9a6b549c4899250f6e116630Kim Phillips ret = phy_driver_register(&dm9161a_driver); 19700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (ret) 19800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming goto err2; 19912414db11da8789d9a6b549c4899250f6e116630Kim Phillips 20012414db11da8789d9a6b549c4899250f6e116630Kim Phillips ret = phy_driver_register(&dm9131_driver); 20112414db11da8789d9a6b549c4899250f6e116630Kim Phillips if (ret) 20212414db11da8789d9a6b549c4899250f6e116630Kim Phillips goto err3; 20300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return 0; 20400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 20512414db11da8789d9a6b549c4899250f6e116630Kim Phillips err3: 20612414db11da8789d9a6b549c4899250f6e116630Kim Phillips phy_driver_unregister(&dm9161a_driver); 20712414db11da8789d9a6b549c4899250f6e116630Kim Phillips err2: 20812414db11da8789d9a6b549c4899250f6e116630Kim Phillips phy_driver_unregister(&dm9161e_driver); 20900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err1: 21000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return ret; 21100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 21200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 21300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingstatic void __exit davicom_exit(void) 21400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 21512414db11da8789d9a6b549c4899250f6e116630Kim Phillips phy_driver_unregister(&dm9161e_driver); 21612414db11da8789d9a6b549c4899250f6e116630Kim Phillips phy_driver_unregister(&dm9161a_driver); 21700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phy_driver_unregister(&dm9131_driver); 21800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 21900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 22000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingmodule_init(davicom_init); 22100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingmodule_exit(davicom_exit); 222