root/drivers/pci/hotplug/cpcihp_zt5550.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zt5550_hc_config
  2. zt5550_hc_cleanup
  3. zt5550_hc_query_enum
  4. zt5550_hc_check_irq
  5. zt5550_hc_enable_irq
  6. zt5550_hc_disable_irq
  7. zt5550_hc_init_one
  8. zt5550_hc_remove_one
  9. zt5550_init
  10. zt5550_exit

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * cpcihp_zt5550.c
   4  *
   5  * Intel/Ziatech ZT5550 CompactPCI Host Controller driver
   6  *
   7  * Copyright 2002 SOMA Networks, Inc.
   8  * Copyright 2001 Intel San Luis Obispo
   9  * Copyright 2000,2001 MontaVista Software Inc.
  10  *
  11  * Send feedback to <scottm@somanetworks.com>
  12  */
  13 
  14 #include <linux/module.h>
  15 #include <linux/moduleparam.h>
  16 #include <linux/init.h>
  17 #include <linux/errno.h>
  18 #include <linux/pci.h>
  19 #include <linux/interrupt.h>
  20 #include <linux/signal.h>       /* IRQF_SHARED */
  21 #include "cpci_hotplug.h"
  22 #include "cpcihp_zt5550.h"
  23 
  24 #define DRIVER_VERSION  "0.2"
  25 #define DRIVER_AUTHOR   "Scott Murray <scottm@somanetworks.com>"
  26 #define DRIVER_DESC     "ZT5550 CompactPCI Hot Plug Driver"
  27 
  28 #define MY_NAME "cpcihp_zt5550"
  29 
  30 #define dbg(format, arg...)                                     \
  31         do {                                                    \
  32                 if (debug)                                      \
  33                         printk(KERN_DEBUG "%s: " format "\n",   \
  34                                 MY_NAME, ## arg);               \
  35         } while (0)
  36 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME, ## arg)
  37 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME, ## arg)
  38 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME, ## arg)
  39 
  40 /* local variables */
  41 static bool debug;
  42 static bool poll;
  43 static struct cpci_hp_controller_ops zt5550_hpc_ops;
  44 static struct cpci_hp_controller zt5550_hpc;
  45 
  46 /* Primary cPCI bus bridge device */
  47 static struct pci_dev *bus0_dev;
  48 static struct pci_bus *bus0;
  49 
  50 /* Host controller device */
  51 static struct pci_dev *hc_dev;
  52 
  53 /* Host controller register addresses */
  54 static void __iomem *hc_registers;
  55 static void __iomem *csr_hc_index;
  56 static void __iomem *csr_hc_data;
  57 static void __iomem *csr_int_status;
  58 static void __iomem *csr_int_mask;
  59 
  60 
  61 static int zt5550_hc_config(struct pci_dev *pdev)
  62 {
  63         int ret;
  64 
  65         /* Since we know that no boards exist with two HC chips, treat it as an error */
  66         if (hc_dev) {
  67                 err("too many host controller devices?");
  68                 return -EBUSY;
  69         }
  70 
  71         ret = pci_enable_device(pdev);
  72         if (ret) {
  73                 err("cannot enable %s\n", pci_name(pdev));
  74                 return ret;
  75         }
  76 
  77         hc_dev = pdev;
  78         dbg("hc_dev = %p", hc_dev);
  79         dbg("pci resource start %llx", (unsigned long long)pci_resource_start(hc_dev, 1));
  80         dbg("pci resource len %llx", (unsigned long long)pci_resource_len(hc_dev, 1));
  81 
  82         if (!request_mem_region(pci_resource_start(hc_dev, 1),
  83                                 pci_resource_len(hc_dev, 1), MY_NAME)) {
  84                 err("cannot reserve MMIO region");
  85                 ret = -ENOMEM;
  86                 goto exit_disable_device;
  87         }
  88 
  89         hc_registers =
  90             ioremap(pci_resource_start(hc_dev, 1), pci_resource_len(hc_dev, 1));
  91         if (!hc_registers) {
  92                 err("cannot remap MMIO region %llx @ %llx",
  93                         (unsigned long long)pci_resource_len(hc_dev, 1),
  94                         (unsigned long long)pci_resource_start(hc_dev, 1));
  95                 ret = -ENODEV;
  96                 goto exit_release_region;
  97         }
  98 
  99         csr_hc_index = hc_registers + CSR_HCINDEX;
 100         csr_hc_data = hc_registers + CSR_HCDATA;
 101         csr_int_status = hc_registers + CSR_INTSTAT;
 102         csr_int_mask = hc_registers + CSR_INTMASK;
 103 
 104         /*
 105          * Disable host control, fault and serial interrupts
 106          */
 107         dbg("disabling host control, fault and serial interrupts");
 108         writeb((u8) HC_INT_MASK_REG, csr_hc_index);
 109         writeb((u8) ALL_INDEXED_INTS_MASK, csr_hc_data);
 110         dbg("disabled host control, fault and serial interrupts");
 111 
 112         /*
 113          * Disable timer0, timer1 and ENUM interrupts
 114          */
 115         dbg("disabling timer0, timer1 and ENUM interrupts");
 116         writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
 117         dbg("disabled timer0, timer1 and ENUM interrupts");
 118         return 0;
 119 
 120 exit_release_region:
 121         release_mem_region(pci_resource_start(hc_dev, 1),
 122                            pci_resource_len(hc_dev, 1));
 123 exit_disable_device:
 124         pci_disable_device(hc_dev);
 125         return ret;
 126 }
 127 
 128 static int zt5550_hc_cleanup(void)
 129 {
 130         if (!hc_dev)
 131                 return -ENODEV;
 132 
 133         iounmap(hc_registers);
 134         release_mem_region(pci_resource_start(hc_dev, 1),
 135                            pci_resource_len(hc_dev, 1));
 136         pci_disable_device(hc_dev);
 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         reg = readb(csr_int_mask);
 183         reg = reg | ENUM_INT_MASK;
 184         writeb(reg, csr_int_mask);
 185         return 0;
 186 }
 187 
 188 static int zt5550_hc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 189 {
 190         int status;
 191 
 192         status = zt5550_hc_config(pdev);
 193         if (status != 0)
 194                 return status;
 195 
 196         dbg("returned from zt5550_hc_config");
 197 
 198         memset(&zt5550_hpc, 0, sizeof(struct cpci_hp_controller));
 199         zt5550_hpc_ops.query_enum = zt5550_hc_query_enum;
 200         zt5550_hpc.ops = &zt5550_hpc_ops;
 201         if (!poll) {
 202                 zt5550_hpc.irq = hc_dev->irq;
 203                 zt5550_hpc.irq_flags = IRQF_SHARED;
 204                 zt5550_hpc.dev_id = hc_dev;
 205 
 206                 zt5550_hpc_ops.enable_irq = zt5550_hc_enable_irq;
 207                 zt5550_hpc_ops.disable_irq = zt5550_hc_disable_irq;
 208                 zt5550_hpc_ops.check_irq = zt5550_hc_check_irq;
 209         } else {
 210                 info("using ENUM# polling mode");
 211         }
 212 
 213         status = cpci_hp_register_controller(&zt5550_hpc);
 214         if (status != 0) {
 215                 err("could not register cPCI hotplug controller");
 216                 goto init_hc_error;
 217         }
 218         dbg("registered controller");
 219 
 220         /* Look for first device matching cPCI bus's bridge vendor and device IDs */
 221         bus0_dev = pci_get_device(PCI_VENDOR_ID_DEC,
 222                                   PCI_DEVICE_ID_DEC_21154, NULL);
 223         if (!bus0_dev) {
 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 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 const 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         = zt5550_hc_remove_one,
 275 };
 276 
 277 static int __init zt5550_init(void)
 278 {
 279         struct resource *r;
 280         int rc;
 281 
 282         info(DRIVER_DESC " version: " DRIVER_VERSION);
 283         r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register");
 284         if (!r)
 285                 return -EBUSY;
 286 
 287         rc = pci_register_driver(&zt5550_hc_driver);
 288         if (rc < 0)
 289                 release_region(ENUM_PORT, 1);
 290         return rc;
 291 }
 292 
 293 static void __exit
 294 zt5550_exit(void)
 295 {
 296         pci_unregister_driver(&zt5550_hc_driver);
 297         release_region(ENUM_PORT, 1);
 298 }
 299 
 300 module_init(zt5550_init);
 301 module_exit(zt5550_exit);
 302 
 303 MODULE_AUTHOR(DRIVER_AUTHOR);
 304 MODULE_DESCRIPTION(DRIVER_DESC);
 305 MODULE_LICENSE("GPL");
 306 module_param(debug, bool, 0644);
 307 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 308 module_param(poll, bool, 0644);
 309 MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not");

/* [<][>][^][v][top][bottom][index][help] */