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