1 /* 2 * cpcihp_zt5550.c 3 * 4 * Intel/Ziatech ZT5550 CompactPCI Host Controller driver 5 * 6 * Copyright 2002 SOMA Networks, Inc. 7 * Copyright 2001 Intel San Luis Obispo 8 * Copyright 2000,2001 MontaVista Software Inc. 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the 12 * Free Software Foundation; either version 2 of the License, or (at your 13 * option) any later version. 14 * 15 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 16 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 17 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 18 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * You should have received a copy of the GNU General Public License along 27 * with this program; if not, write to the Free Software Foundation, Inc., 28 * 675 Mass Ave, Cambridge, MA 02139, USA. 29 * 30 * Send feedback to <scottm@somanetworks.com> 31 */ 32 33 #include <linux/config.h> 34 #include <linux/module.h> 35 #include <linux/moduleparam.h> 36 #include <linux/init.h> 37 #include <linux/errno.h> 38 #include <linux/pci.h> 39 #include "cpci_hotplug.h" 40 #include "cpcihp_zt5550.h" 41 42 #define DRIVER_VERSION "0.2" 43 #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" 44 #define DRIVER_DESC "ZT5550 CompactPCI Hot Plug Driver" 45 46 #define MY_NAME "cpcihp_zt5550" 47 48 #define dbg(format, arg...) \ 49 do { \ 50 if(debug) \ 51 printk (KERN_DEBUG "%s: " format "\n", \ 52 MY_NAME , ## arg); \ 53 } while(0) 54 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) 55 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) 56 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) 57 58 /* local variables */ 59 static int debug; 60 static int poll; 61 static struct cpci_hp_controller_ops zt5550_hpc_ops; 62 static struct cpci_hp_controller zt5550_hpc; 63 64 /* Primary cPCI bus bridge device */ 65 static struct pci_dev *bus0_dev; 66 static struct pci_bus *bus0; 67 68 /* Host controller device */ 69 static struct pci_dev *hc_dev; 70 71 /* Host controller register addresses */ 72 static void __iomem *hc_registers; 73 static void __iomem *csr_hc_index; 74 static void __iomem *csr_hc_data; 75 static void __iomem *csr_int_status; 76 static void __iomem *csr_int_mask; 77 78 79 static int zt5550_hc_config(struct pci_dev *pdev) 80 { 81 /* Since we know that no boards exist with two HC chips, treat it as an error */ 82 if(hc_dev) { 83 err("too many host controller devices?"); 84 return -EBUSY; 85 } 86 hc_dev = pdev; 87 dbg("hc_dev = %p", hc_dev); 88 dbg("pci resource start %lx", pci_resource_start(hc_dev, 1)); 89 dbg("pci resource len %lx", pci_resource_len(hc_dev, 1)); 90 91 if(!request_mem_region(pci_resource_start(hc_dev, 1), 92 pci_resource_len(hc_dev, 1), MY_NAME)) { 93 err("cannot reserve MMIO region"); 94 return -ENOMEM; 95 } 96 97 hc_registers = 98 ioremap(pci_resource_start(hc_dev, 1), pci_resource_len(hc_dev, 1)); 99 if(!hc_registers) { 100 err("cannot remap MMIO region %lx @ %lx", 101 pci_resource_len(hc_dev, 1), pci_resource_start(hc_dev, 1)); 102 release_mem_region(pci_resource_start(hc_dev, 1), 103 pci_resource_len(hc_dev, 1)); 104 return -ENODEV; 105 } 106 107 csr_hc_index = hc_registers + CSR_HCINDEX; 108 csr_hc_data = hc_registers + CSR_HCDATA; 109 csr_int_status = hc_registers + CSR_INTSTAT; 110 csr_int_mask = hc_registers + CSR_INTMASK; 111 112 /* 113 * Disable host control, fault and serial interrupts 114 */ 115 dbg("disabling host control, fault and serial interrupts"); 116 writeb((u8) HC_INT_MASK_REG, csr_hc_index); 117 writeb((u8) ALL_INDEXED_INTS_MASK, csr_hc_data); 118 dbg("disabled host control, fault and serial interrupts"); 119 120 /* 121 * Disable timer0, timer1 and ENUM interrupts 122 */ 123 dbg("disabling timer0, timer1 and ENUM interrupts"); 124 writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask); 125 dbg("disabled timer0, timer1 and ENUM interrupts"); 126 return 0; 127 } 128 129 static int zt5550_hc_cleanup(void) 130 { 131 if(!hc_dev) 132 return -ENODEV; 133 134 iounmap(hc_registers); 135 release_mem_region(pci_resource_start(hc_dev, 1), 136 pci_resource_len(hc_dev, 1)); 137 return 0; 138 } 139 140 static int zt5550_hc_query_enum(void) 141 { 142 u8 value; 143 144 value = inb_p(ENUM_PORT); 145 return ((value & ENUM_MASK) == ENUM_MASK); 146 } 147 148 static int zt5550_hc_check_irq(void *dev_id) 149 { 150 int ret; 151 u8 reg; 152 153 ret = 0; 154 if(dev_id == zt5550_hpc.dev_id) { 155 reg = readb(csr_int_status); 156 if(reg) 157 ret = 1; 158 } 159 return ret; 160 } 161 162 static int zt5550_hc_enable_irq(void) 163 { 164 u8 reg; 165 166 if(hc_dev == NULL) { 167 return -ENODEV; 168 } 169 reg = readb(csr_int_mask); 170 reg = reg & ~ENUM_INT_MASK; 171 writeb(reg, csr_int_mask); 172 return 0; 173 } 174 175 static int zt5550_hc_disable_irq(void) 176 { 177 u8 reg; 178 179 if(hc_dev == NULL) { 180 return -ENODEV; 181 } 182 183 reg = readb(csr_int_mask); 184 reg = reg | ENUM_INT_MASK; 185 writeb(reg, csr_int_mask); 186 return 0; 187 } 188 189 static int zt5550_hc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) 190 { 191 int status; 192 193 status = zt5550_hc_config(pdev); 194 if(status != 0) { 195 return status; 196 } 197 dbg("returned from zt5550_hc_config"); 198 199 memset(&zt5550_hpc, 0, sizeof (struct cpci_hp_controller)); 200 zt5550_hpc_ops.query_enum = zt5550_hc_query_enum; 201 zt5550_hpc.ops = &zt5550_hpc_ops; 202 if(!poll) { 203 zt5550_hpc.irq = hc_dev->irq; 204 zt5550_hpc.irq_flags = SA_SHIRQ; 205 zt5550_hpc.dev_id = hc_dev; 206 207 zt5550_hpc_ops.enable_irq = zt5550_hc_enable_irq; 208 zt5550_hpc_ops.disable_irq = zt5550_hc_disable_irq; 209 zt5550_hpc_ops.check_irq = zt5550_hc_check_irq; 210 } else { 211 info("using ENUM# polling mode"); 212 } 213 214 status = cpci_hp_register_controller(&zt5550_hpc); 215 if(status != 0) { 216 err("could not register cPCI hotplug controller"); 217 goto init_hc_error; 218 } 219 dbg("registered controller"); 220 221 /* Look for first device matching cPCI bus's bridge vendor and device IDs */ 222 if(!(bus0_dev = pci_get_device(PCI_VENDOR_ID_DEC, 223 PCI_DEVICE_ID_DEC_21154, NULL))) { 224 status = -ENODEV; 225 goto init_register_error; 226 } 227 bus0 = bus0_dev->subordinate; 228 pci_dev_put(bus0_dev); 229 230 status = cpci_hp_register_bus(bus0, 0x0a, 0x0f); 231 if(status != 0) { 232 err("could not register cPCI hotplug bus"); 233 goto init_register_error; 234 } 235 dbg("registered bus"); 236 237 status = cpci_hp_start(); 238 if(status != 0) { 239 err("could not started cPCI hotplug system"); 240 cpci_hp_unregister_bus(bus0); 241 goto init_register_error; 242 } 243 dbg("started cpci hp system"); 244 245 return 0; 246 init_register_error: 247 cpci_hp_unregister_controller(&zt5550_hpc); 248 init_hc_error: 249 err("status = %d", status); 250 zt5550_hc_cleanup(); 251 return status; 252 253 } 254 255 static void __devexit zt5550_hc_remove_one(struct pci_dev *pdev) 256 { 257 cpci_hp_stop(); 258 cpci_hp_unregister_bus(bus0); 259 cpci_hp_unregister_controller(&zt5550_hpc); 260 zt5550_hc_cleanup(); 261 } 262 263 264 static struct pci_device_id zt5550_hc_pci_tbl[] = { 265 { PCI_VENDOR_ID_ZIATECH, PCI_DEVICE_ID_ZIATECH_5550_HC, PCI_ANY_ID, PCI_ANY_ID, }, 266 { 0, } 267 }; 268 MODULE_DEVICE_TABLE(pci, zt5550_hc_pci_tbl); 269 270 static struct pci_driver zt5550_hc_driver = { 271 .name = "zt5550_hc", 272 .id_table = zt5550_hc_pci_tbl, 273 .probe = zt5550_hc_init_one, 274 .remove = __devexit_p(zt5550_hc_remove_one), 275 }; 276 277 static int __init zt5550_init(void) 278 { 279 struct resource* r; 280 281 info(DRIVER_DESC " version: " DRIVER_VERSION); 282 r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register"); 283 if(!r) 284 return -EBUSY; 285 286 return pci_register_driver(&zt5550_hc_driver); 287 } 288 289 static void __exit 290 zt5550_exit(void) 291 { 292 pci_unregister_driver(&zt5550_hc_driver); 293 release_region(ENUM_PORT, 1); 294 } 295 296 module_init(zt5550_init); 297 module_exit(zt5550_exit); 298 299 MODULE_AUTHOR(DRIVER_AUTHOR); 300 MODULE_DESCRIPTION(DRIVER_DESC); 301 MODULE_LICENSE("GPL"); 302 module_param(debug, bool, 0644); 303 MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); 304 module_param(poll, bool, 0644); 305 MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not"); 306