1 /* 2 * Copyright (C) 2016 Cavium, Inc. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License 6 * as published by the Free Software Foundation. 7 */ 8 9 #include <linux/acpi.h> 10 #include <linux/module.h> 11 #include <linux/interrupt.h> 12 #include <linux/pci.h> 13 #include <linux/netdevice.h> 14 #include <linux/etherdevice.h> 15 #include <linux/phy.h> 16 #include <linux/of.h> 17 #include <linux/of_mdio.h> 18 #include <linux/of_net.h> 19 20 #include "nic.h" 21 #include "thunder_bgx.h" 22 23 #define DRV_NAME "thunder-xcv" 24 #define DRV_VERSION "1.0" 25 26 /* Register offsets */ 27 #define XCV_RESET 0x00 28 #define PORT_EN BIT_ULL(63) 29 #define CLK_RESET BIT_ULL(15) 30 #define DLL_RESET BIT_ULL(11) 31 #define COMP_EN BIT_ULL(7) 32 #define TX_PKT_RESET BIT_ULL(3) 33 #define TX_DATA_RESET BIT_ULL(2) 34 #define RX_PKT_RESET BIT_ULL(1) 35 #define RX_DATA_RESET BIT_ULL(0) 36 #define XCV_DLL_CTL 0x10 37 #define CLKRX_BYP BIT_ULL(23) 38 #define CLKTX_BYP BIT_ULL(15) 39 #define XCV_COMP_CTL 0x20 40 #define DRV_BYP BIT_ULL(63) 41 #define XCV_CTL 0x30 42 #define XCV_INT 0x40 43 #define XCV_INT_W1S 0x48 44 #define XCV_INT_ENA_W1C 0x50 45 #define XCV_INT_ENA_W1S 0x58 46 #define XCV_INBND_STATUS 0x80 47 #define XCV_BATCH_CRD_RET 0x100 48 49 struct xcv { 50 void __iomem *reg_base; 51 struct pci_dev *pdev; 52 }; 53 54 static struct xcv *xcv; 55 56 /* Supported devices */ 57 static const struct pci_device_id xcv_id_table[] = { 58 { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xA056) }, 59 { 0, } /* end of table */ 60 }; 61 62 MODULE_AUTHOR("Cavium Inc"); 63 MODULE_DESCRIPTION("Cavium Thunder RGX/XCV Driver"); 64 MODULE_LICENSE("GPL v2"); 65 MODULE_VERSION(DRV_VERSION); 66 MODULE_DEVICE_TABLE(pci, xcv_id_table); 67 68 void xcv_init_hw(void) 69 { 70 u64 cfg; 71 72 /* Take DLL out of reset */ 73 cfg = readq_relaxed(xcv->reg_base + XCV_RESET); 74 cfg &= ~DLL_RESET; 75 writeq_relaxed(cfg, xcv->reg_base + XCV_RESET); 76 77 /* Take clock tree out of reset */ 78 cfg = readq_relaxed(xcv->reg_base + XCV_RESET); 79 cfg &= ~CLK_RESET; 80 writeq_relaxed(cfg, xcv->reg_base + XCV_RESET); 81 /* Wait for DLL to lock */ 82 msleep(1); 83 84 /* Configure DLL - enable or bypass 85 * TX no bypass, RX bypass 86 */ 87 cfg = readq_relaxed(xcv->reg_base + XCV_DLL_CTL); 88 cfg &= ~0xFF03; 89 cfg |= CLKRX_BYP; 90 writeq_relaxed(cfg, xcv->reg_base + XCV_DLL_CTL); 91 92 /* Enable compensation controller and force the 93 * write to be visible to HW by readig back. 94 */ 95 cfg = readq_relaxed(xcv->reg_base + XCV_RESET); 96 cfg |= COMP_EN; 97 writeq_relaxed(cfg, xcv->reg_base + XCV_RESET); 98 readq_relaxed(xcv->reg_base + XCV_RESET); 99 /* Wait for compensation state machine to lock */ 100 msleep(10); 101 102 /* enable the XCV block */ 103 cfg = readq_relaxed(xcv->reg_base + XCV_RESET); 104 cfg |= PORT_EN; 105 writeq_relaxed(cfg, xcv->reg_base + XCV_RESET); 106 107 cfg = readq_relaxed(xcv->reg_base + XCV_RESET); 108 cfg |= CLK_RESET; 109 writeq_relaxed(cfg, xcv->reg_base + XCV_RESET); 110 } 111 EXPORT_SYMBOL(xcv_init_hw); 112 113 void xcv_setup_link(bool link_up, int link_speed) 114 { 115 u64 cfg; 116 int speed = 2; 117 118 if (!xcv) { 119 dev_err(&xcv->pdev->dev, 120 "XCV init not done, probe may have failed\n"); 121 return; 122 } 123 124 if (link_speed == 100) 125 speed = 1; 126 else if (link_speed == 10) 127 speed = 0; 128 129 if (link_up) { 130 /* set operating speed */ 131 cfg = readq_relaxed(xcv->reg_base + XCV_CTL); 132 cfg &= ~0x03; 133 cfg |= speed; 134 writeq_relaxed(cfg, xcv->reg_base + XCV_CTL); 135 136 /* Reset datapaths */ 137 cfg = readq_relaxed(xcv->reg_base + XCV_RESET); 138 cfg |= TX_DATA_RESET | RX_DATA_RESET; 139 writeq_relaxed(cfg, xcv->reg_base + XCV_RESET); 140 141 /* Enable the packet flow */ 142 cfg = readq_relaxed(xcv->reg_base + XCV_RESET); 143 cfg |= TX_PKT_RESET | RX_PKT_RESET; 144 writeq_relaxed(cfg, xcv->reg_base + XCV_RESET); 145 146 /* Return credits to RGX */ 147 writeq_relaxed(0x01, xcv->reg_base + XCV_BATCH_CRD_RET); 148 } else { 149 /* Disable packet flow */ 150 cfg = readq_relaxed(xcv->reg_base + XCV_RESET); 151 cfg &= ~(TX_PKT_RESET | RX_PKT_RESET); 152 writeq_relaxed(cfg, xcv->reg_base + XCV_RESET); 153 readq_relaxed(xcv->reg_base + XCV_RESET); 154 } 155 } 156 EXPORT_SYMBOL(xcv_setup_link); 157 158 static int xcv_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 159 { 160 int err; 161 struct device *dev = &pdev->dev; 162 163 xcv = devm_kzalloc(dev, sizeof(struct xcv), GFP_KERNEL); 164 if (!xcv) 165 return -ENOMEM; 166 xcv->pdev = pdev; 167 168 pci_set_drvdata(pdev, xcv); 169 170 err = pci_enable_device(pdev); 171 if (err) { 172 dev_err(dev, "Failed to enable PCI device\n"); 173 goto err_kfree; 174 } 175 176 err = pci_request_regions(pdev, DRV_NAME); 177 if (err) { 178 dev_err(dev, "PCI request regions failed 0x%x\n", err); 179 goto err_disable_device; 180 } 181 182 /* MAP configuration registers */ 183 xcv->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0); 184 if (!xcv->reg_base) { 185 dev_err(dev, "XCV: Cannot map CSR memory space, aborting\n"); 186 err = -ENOMEM; 187 goto err_release_regions; 188 } 189 190 return 0; 191 192 err_release_regions: 193 pci_release_regions(pdev); 194 err_disable_device: 195 pci_disable_device(pdev); 196 err_kfree: 197 devm_kfree(dev, xcv); 198 xcv = NULL; 199 return err; 200 } 201 202 static void xcv_remove(struct pci_dev *pdev) 203 { 204 struct device *dev = &pdev->dev; 205 206 if (xcv) { 207 devm_kfree(dev, xcv); 208 xcv = NULL; 209 } 210 211 pci_release_regions(pdev); 212 pci_disable_device(pdev); 213 } 214 215 static struct pci_driver xcv_driver = { 216 .name = DRV_NAME, 217 .id_table = xcv_id_table, 218 .probe = xcv_probe, 219 .remove = xcv_remove, 220 }; 221 222 static int __init xcv_init_module(void) 223 { 224 pr_info("%s, ver %s\n", DRV_NAME, DRV_VERSION); 225 226 return pci_register_driver(&xcv_driver); 227 } 228 229 static void __exit xcv_cleanup_module(void) 230 { 231 pci_unregister_driver(&xcv_driver); 232 } 233 234 module_init(xcv_init_module); 235 module_exit(xcv_cleanup_module); 236