LCOV - code coverage report
Current view: top level - drivers/pci/hotplug - cpcihp_zt5550.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 8 134 6.0 %
Date: 2022-04-01 13:59:58 Functions: 1 10 10.0 %
Branches: 2 82 2.4 %

           Branch data     Line data    Source code
       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                 :          0 : static int zt5550_hc_config(struct pci_dev *pdev)
      62                 :            : {
      63                 :          0 :         int ret;
      64                 :            : 
      65                 :            :         /* Since we know that no boards exist with two HC chips, treat it as an error */
      66         [ #  # ]:          0 :         if (hc_dev) {
      67                 :          0 :                 err("too many host controller devices?");
      68                 :          0 :                 return -EBUSY;
      69                 :            :         }
      70                 :            : 
      71                 :          0 :         ret = pci_enable_device(pdev);
      72         [ #  # ]:          0 :         if (ret) {
      73         [ #  # ]:          0 :                 err("cannot enable %s\n", pci_name(pdev));
      74                 :          0 :                 return ret;
      75                 :            :         }
      76                 :            : 
      77                 :          0 :         hc_dev = pdev;
      78         [ #  # ]:          0 :         dbg("hc_dev = %p", hc_dev);
      79         [ #  # ]:          0 :         dbg("pci resource start %llx", (unsigned long long)pci_resource_start(hc_dev, 1));
      80   [ #  #  #  #  :          0 :         dbg("pci resource len %llx", (unsigned long long)pci_resource_len(hc_dev, 1));
                   #  # ]
      81                 :            : 
      82   [ #  #  #  #  :          0 :         if (!request_mem_region(pci_resource_start(hc_dev, 1),
                   #  # ]
      83                 :            :                                 pci_resource_len(hc_dev, 1), MY_NAME)) {
      84                 :          0 :                 err("cannot reserve MMIO region");
      85                 :          0 :                 ret = -ENOMEM;
      86                 :          0 :                 goto exit_disable_device;
      87                 :            :         }
      88                 :            : 
      89                 :          0 :         hc_registers =
      90   [ #  #  #  # ]:          0 :             ioremap(pci_resource_start(hc_dev, 1), pci_resource_len(hc_dev, 1));
      91         [ #  # ]:          0 :         if (!hc_registers) {
      92   [ #  #  #  # ]:          0 :                 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                 :          0 :                 ret = -ENODEV;
      96                 :          0 :                 goto exit_release_region;
      97                 :            :         }
      98                 :            : 
      99                 :          0 :         csr_hc_index = hc_registers + CSR_HCINDEX;
     100                 :          0 :         csr_hc_data = hc_registers + CSR_HCDATA;
     101                 :          0 :         csr_int_status = hc_registers + CSR_INTSTAT;
     102                 :          0 :         csr_int_mask = hc_registers + CSR_INTMASK;
     103                 :            : 
     104                 :            :         /*
     105                 :            :          * Disable host control, fault and serial interrupts
     106                 :            :          */
     107         [ #  # ]:          0 :         dbg("disabling host control, fault and serial interrupts");
     108                 :          0 :         writeb((u8) HC_INT_MASK_REG, csr_hc_index);
     109                 :          0 :         writeb((u8) ALL_INDEXED_INTS_MASK, csr_hc_data);
     110         [ #  # ]:          0 :         dbg("disabled host control, fault and serial interrupts");
     111                 :            : 
     112                 :            :         /*
     113                 :            :          * Disable timer0, timer1 and ENUM interrupts
     114                 :            :          */
     115         [ #  # ]:          0 :         dbg("disabling timer0, timer1 and ENUM interrupts");
     116                 :          0 :         writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
     117         [ #  # ]:          0 :         dbg("disabled timer0, timer1 and ENUM interrupts");
     118                 :            :         return 0;
     119                 :            : 
     120                 :            : exit_release_region:
     121   [ #  #  #  # ]:          0 :         release_mem_region(pci_resource_start(hc_dev, 1),
     122                 :            :                            pci_resource_len(hc_dev, 1));
     123                 :          0 : exit_disable_device:
     124                 :          0 :         pci_disable_device(hc_dev);
     125                 :          0 :         return ret;
     126                 :            : }
     127                 :            : 
     128                 :          0 : static int zt5550_hc_cleanup(void)
     129                 :            : {
     130         [ #  # ]:          0 :         if (!hc_dev)
     131                 :            :                 return -ENODEV;
     132                 :            : 
     133                 :          0 :         iounmap(hc_registers);
     134   [ #  #  #  # ]:          0 :         release_mem_region(pci_resource_start(hc_dev, 1),
     135                 :            :                            pci_resource_len(hc_dev, 1));
     136                 :          0 :         pci_disable_device(hc_dev);
     137                 :          0 :         return 0;
     138                 :            : }
     139                 :            : 
     140                 :          0 : static int zt5550_hc_query_enum(void)
     141                 :            : {
     142                 :          0 :         u8 value;
     143                 :            : 
     144                 :          0 :         value = inb_p(ENUM_PORT);
     145                 :          0 :         return ((value & ENUM_MASK) == ENUM_MASK);
     146                 :            : }
     147                 :            : 
     148                 :          0 : static int zt5550_hc_check_irq(void *dev_id)
     149                 :            : {
     150                 :          0 :         int ret;
     151                 :          0 :         u8 reg;
     152                 :            : 
     153                 :          0 :         ret = 0;
     154         [ #  # ]:          0 :         if (dev_id == zt5550_hpc.dev_id) {
     155                 :          0 :                 reg = readb(csr_int_status);
     156         [ #  # ]:          0 :                 if (reg)
     157                 :          0 :                         ret = 1;
     158                 :            :         }
     159                 :          0 :         return ret;
     160                 :            : }
     161                 :            : 
     162                 :          0 : static int zt5550_hc_enable_irq(void)
     163                 :            : {
     164                 :          0 :         u8 reg;
     165                 :            : 
     166         [ #  # ]:          0 :         if (hc_dev == NULL)
     167                 :            :                 return -ENODEV;
     168                 :            : 
     169                 :          0 :         reg = readb(csr_int_mask);
     170                 :          0 :         reg = reg & ~ENUM_INT_MASK;
     171                 :          0 :         writeb(reg, csr_int_mask);
     172                 :          0 :         return 0;
     173                 :            : }
     174                 :            : 
     175                 :          0 : static int zt5550_hc_disable_irq(void)
     176                 :            : {
     177                 :          0 :         u8 reg;
     178                 :            : 
     179         [ #  # ]:          0 :         if (hc_dev == NULL)
     180                 :            :                 return -ENODEV;
     181                 :            : 
     182                 :          0 :         reg = readb(csr_int_mask);
     183                 :          0 :         reg = reg | ENUM_INT_MASK;
     184                 :          0 :         writeb(reg, csr_int_mask);
     185                 :          0 :         return 0;
     186                 :            : }
     187                 :            : 
     188                 :          0 : static int zt5550_hc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
     189                 :            : {
     190                 :          0 :         int status;
     191                 :            : 
     192                 :          0 :         status = zt5550_hc_config(pdev);
     193         [ #  # ]:          0 :         if (status != 0)
     194                 :            :                 return status;
     195                 :            : 
     196         [ #  # ]:          0 :         dbg("returned from zt5550_hc_config");
     197                 :            : 
     198                 :          0 :         memset(&zt5550_hpc, 0, sizeof(struct cpci_hp_controller));
     199                 :          0 :         zt5550_hpc_ops.query_enum = zt5550_hc_query_enum;
     200                 :          0 :         zt5550_hpc.ops = &zt5550_hpc_ops;
     201         [ #  # ]:          0 :         if (!poll) {
     202                 :          0 :                 zt5550_hpc.irq = hc_dev->irq;
     203                 :          0 :                 zt5550_hpc.irq_flags = IRQF_SHARED;
     204                 :          0 :                 zt5550_hpc.dev_id = hc_dev;
     205                 :            : 
     206                 :          0 :                 zt5550_hpc_ops.enable_irq = zt5550_hc_enable_irq;
     207                 :          0 :                 zt5550_hpc_ops.disable_irq = zt5550_hc_disable_irq;
     208                 :          0 :                 zt5550_hpc_ops.check_irq = zt5550_hc_check_irq;
     209                 :            :         } else {
     210                 :          0 :                 info("using ENUM# polling mode");
     211                 :            :         }
     212                 :            : 
     213                 :          0 :         status = cpci_hp_register_controller(&zt5550_hpc);
     214         [ #  # ]:          0 :         if (status != 0) {
     215                 :          0 :                 err("could not register cPCI hotplug controller");
     216                 :          0 :                 goto init_hc_error;
     217                 :            :         }
     218         [ #  # ]:          0 :         dbg("registered controller");
     219                 :            : 
     220                 :            :         /* Look for first device matching cPCI bus's bridge vendor and device IDs */
     221                 :          0 :         bus0_dev = pci_get_device(PCI_VENDOR_ID_DEC,
     222                 :            :                                   PCI_DEVICE_ID_DEC_21154, NULL);
     223         [ #  # ]:          0 :         if (!bus0_dev) {
     224                 :          0 :                 status = -ENODEV;
     225                 :          0 :                 goto init_register_error;
     226                 :            :         }
     227                 :          0 :         bus0 = bus0_dev->subordinate;
     228                 :          0 :         pci_dev_put(bus0_dev);
     229                 :            : 
     230                 :          0 :         status = cpci_hp_register_bus(bus0, 0x0a, 0x0f);
     231         [ #  # ]:          0 :         if (status != 0) {
     232                 :          0 :                 err("could not register cPCI hotplug bus");
     233                 :          0 :                 goto init_register_error;
     234                 :            :         }
     235         [ #  # ]:          0 :         dbg("registered bus");
     236                 :            : 
     237                 :          0 :         status = cpci_hp_start();
     238         [ #  # ]:          0 :         if (status != 0) {
     239                 :          0 :                 err("could not started cPCI hotplug system");
     240                 :          0 :                 cpci_hp_unregister_bus(bus0);
     241                 :          0 :                 goto init_register_error;
     242                 :            :         }
     243         [ #  # ]:          0 :         dbg("started cpci hp system");
     244                 :            : 
     245                 :            :         return 0;
     246                 :          0 : init_register_error:
     247                 :          0 :         cpci_hp_unregister_controller(&zt5550_hpc);
     248                 :          0 : init_hc_error:
     249                 :          0 :         err("status = %d", status);
     250                 :          0 :         zt5550_hc_cleanup();
     251                 :          0 :         return status;
     252                 :            : 
     253                 :            : }
     254                 :            : 
     255                 :          0 : static void zt5550_hc_remove_one(struct pci_dev *pdev)
     256                 :            : {
     257                 :          0 :         cpci_hp_stop();
     258                 :          0 :         cpci_hp_unregister_bus(bus0);
     259                 :          0 :         cpci_hp_unregister_controller(&zt5550_hpc);
     260                 :          0 :         zt5550_hc_cleanup();
     261                 :          0 : }
     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                 :         78 : static int __init zt5550_init(void)
     278                 :            : {
     279                 :         78 :         struct resource *r;
     280                 :         78 :         int rc;
     281                 :            : 
     282                 :         78 :         info(DRIVER_DESC " version: " DRIVER_VERSION);
     283                 :         78 :         r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register");
     284         [ +  - ]:         78 :         if (!r)
     285                 :            :                 return -EBUSY;
     286                 :            : 
     287                 :         78 :         rc = pci_register_driver(&zt5550_hc_driver);
     288         [ -  + ]:         78 :         if (rc < 0)
     289                 :          0 :                 release_region(ENUM_PORT, 1);
     290                 :            :         return rc;
     291                 :            : }
     292                 :            : 
     293                 :            : static void __exit
     294                 :          0 : zt5550_exit(void)
     295                 :            : {
     296                 :          0 :         pci_unregister_driver(&zt5550_hc_driver);
     297                 :          0 :         release_region(ENUM_PORT, 1);
     298                 :          0 : }
     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");

Generated by: LCOV version 1.14