brintos

brintos / linux-shallow public Read only

0
0
Text · 5.2 KiB · 3ebb937 Raw
232 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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		0x0025#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		0x1034#define   CLKRX_BYP		BIT_ULL(23)35#define   CLKTX_BYP		BIT_ULL(15)36#define XCV_COMP_CTL		0x2037#define   DRV_BYP		BIT_ULL(63)38#define XCV_CTL			0x3039#define XCV_INT			0x4040#define XCV_INT_W1S		0x4841#define XCV_INT_ENA_W1C		0x5042#define XCV_INT_ENA_W1S		0x5843#define XCV_INBND_STATUS	0x8044#define XCV_BATCH_CRD_RET	0x10045 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 bypass82	 * TX no bypass, RX bypass83	 */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 the90	 * 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);232