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 pr_err("XCV init not done, probe may have failed\n"); 120 return; 121 } 122 123 if (link_speed == 100) 124 speed = 1; 125 else if (link_speed == 10) 126 speed = 0; 127 128 if (link_up) { 129 /* set operating speed */ 130 cfg = readq_relaxed(xcv->reg_base + XCV_CTL); 131 cfg &= ~0x03; 132 cfg |= speed; 133 writeq_relaxed(cfg, xcv->reg_base + XCV_CTL); 134 135 /* Reset datapaths */ 136 cfg = readq_relaxed(xcv->reg_base + XCV_RESET); 137 cfg |= TX_DATA_RESET | RX_DATA_RESET; 138 writeq_relaxed(cfg, xcv->reg_base + XCV_RESET); 139 140 /* Enable the packet flow */ 141 cfg = readq_relaxed(xcv->reg_base + XCV_RESET); 142 cfg |= TX_PKT_RESET | RX_PKT_RESET; 143 writeq_relaxed(cfg, xcv->reg_base + XCV_RESET); 144 145 /* Return credits to RGX */ 146 writeq_relaxed(0x01, xcv->reg_base + XCV_BATCH_CRD_RET); 147 } else { 148 /* Disable packet flow */ 149 cfg = readq_relaxed(xcv->reg_base + XCV_RESET); 150 cfg &= ~(TX_PKT_RESET | RX_PKT_RESET); 151 writeq_relaxed(cfg, xcv->reg_base + XCV_RESET); 152 readq_relaxed(xcv->reg_base + XCV_RESET); 153 } 154 } 155 EXPORT_SYMBOL(xcv_setup_link); 156 157 static int xcv_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 158 { 159 int err; 160 struct device *dev = &pdev->dev; 161 162 xcv = devm_kzalloc(dev, sizeof(struct xcv), GFP_KERNEL); 163 if (!xcv) 164 return -ENOMEM; 165 xcv->pdev = pdev; 166 167 pci_set_drvdata(pdev, xcv); 168 169 err = pci_enable_device(pdev); 170 if (err) { 171 dev_err(dev, "Failed to enable PCI device\n"); 172 goto err_kfree; 173 } 174 175 err = pci_request_regions(pdev, DRV_NAME); 176 if (err) { 177 dev_err(dev, "PCI request regions failed 0x%x\n", err); 178 goto err_disable_device; 179 } 180 181 /* MAP configuration registers */ 182 xcv->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0); 183 if (!xcv->reg_base) { 184 dev_err(dev, "XCV: Cannot map CSR memory space, aborting\n"); 185 err = -ENOMEM; 186 goto err_release_regions; 187 } 188 189 return 0; 190 191 err_release_regions: 192 pci_release_regions(pdev); 193 err_disable_device: 194 pci_disable_device(pdev); 195 err_kfree: 196 devm_kfree(dev, xcv); 197 xcv = NULL; 198 return err; 199 } 200 201 static void xcv_remove(struct pci_dev *pdev) 202 { 203 struct device *dev = &pdev->dev; 204 205 if (xcv) { 206 devm_kfree(dev, xcv); 207 xcv = NULL; 208 } 209 210 pci_release_regions(pdev); 211 pci_disable_device(pdev); 212 } 213 214 static struct pci_driver xcv_driver = { 215 .name = DRV_NAME, 216 .id_table = xcv_id_table, 217 .probe = xcv_probe, 218 .remove = xcv_remove, 219 }; 220 221 static int __init xcv_init_module(void) 222 { 223 pr_info("%s, ver %s\n", DRV_NAME, DRV_VERSION); 224 225 return pci_register_driver(&xcv_driver); 226 } 227 228 static void __exit xcv_cleanup_module(void) 229 { 230 pci_unregister_driver(&xcv_driver); 231 } 232 233 module_init(xcv_init_module); 234 module_exit(xcv_cleanup_module); 235