cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ptp_pch.c (12602B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * PTP 1588 clock using the EG20T PCH
      4 *
      5 * Copyright (C) 2010 OMICRON electronics GmbH
      6 * Copyright (C) 2011-2012 LAPIS SEMICONDUCTOR Co., LTD.
      7 *
      8 * This code was derived from the IXP46X driver.
      9 */
     10
     11#include <linux/device.h>
     12#include <linux/err.h>
     13#include <linux/interrupt.h>
     14#include <linux/io.h>
     15#include <linux/io-64-nonatomic-lo-hi.h>
     16#include <linux/io-64-nonatomic-hi-lo.h>
     17#include <linux/irq.h>
     18#include <linux/kernel.h>
     19#include <linux/module.h>
     20#include <linux/pci.h>
     21#include <linux/ptp_clock_kernel.h>
     22#include <linux/ptp_pch.h>
     23#include <linux/slab.h>
     24
     25#define STATION_ADDR_LEN	20
     26#define PCI_DEVICE_ID_PCH_1588	0x8819
     27#define IO_MEM_BAR 1
     28
     29#define DEFAULT_ADDEND 0xA0000000
     30#define TICKS_NS_SHIFT  5
     31#define N_EXT_TS	2
     32
     33enum pch_status {
     34	PCH_SUCCESS,
     35	PCH_INVALIDPARAM,
     36	PCH_NOTIMESTAMP,
     37	PCH_INTERRUPTMODEINUSE,
     38	PCH_FAILED,
     39	PCH_UNSUPPORTED,
     40};
     41
     42/*
     43 * struct pch_ts_regs - IEEE 1588 registers
     44 */
     45struct pch_ts_regs {
     46	u32 control;
     47	u32 event;
     48	u32 addend;
     49	u32 accum;
     50	u32 test;
     51	u32 ts_compare;
     52	u32 rsystime_lo;
     53	u32 rsystime_hi;
     54	u32 systime_lo;
     55	u32 systime_hi;
     56	u32 trgt_lo;
     57	u32 trgt_hi;
     58	u32 asms_lo;
     59	u32 asms_hi;
     60	u32 amms_lo;
     61	u32 amms_hi;
     62	u32 ch_control;
     63	u32 ch_event;
     64	u32 tx_snap_lo;
     65	u32 tx_snap_hi;
     66	u32 rx_snap_lo;
     67	u32 rx_snap_hi;
     68	u32 src_uuid_lo;
     69	u32 src_uuid_hi;
     70	u32 can_status;
     71	u32 can_snap_lo;
     72	u32 can_snap_hi;
     73	u32 ts_sel;
     74	u32 ts_st[6];
     75	u32 reserve1[14];
     76	u32 stl_max_set_en;
     77	u32 stl_max_set;
     78	u32 reserve2[13];
     79	u32 srst;
     80};
     81
     82#define PCH_TSC_RESET		(1 << 0)
     83#define PCH_TSC_TTM_MASK	(1 << 1)
     84#define PCH_TSC_ASMS_MASK	(1 << 2)
     85#define PCH_TSC_AMMS_MASK	(1 << 3)
     86#define PCH_TSC_PPSM_MASK	(1 << 4)
     87#define PCH_TSE_TTIPEND		(1 << 1)
     88#define PCH_TSE_SNS		(1 << 2)
     89#define PCH_TSE_SNM		(1 << 3)
     90#define PCH_TSE_PPS		(1 << 4)
     91#define PCH_CC_MM		(1 << 0)
     92#define PCH_CC_TA		(1 << 1)
     93
     94#define PCH_CC_MODE_SHIFT	16
     95#define PCH_CC_MODE_MASK	0x001F0000
     96#define PCH_CC_VERSION		(1 << 31)
     97#define PCH_CE_TXS		(1 << 0)
     98#define PCH_CE_RXS		(1 << 1)
     99#define PCH_CE_OVR		(1 << 0)
    100#define PCH_CE_VAL		(1 << 1)
    101#define PCH_ECS_ETH		(1 << 0)
    102
    103#define PCH_ECS_CAN		(1 << 1)
    104
    105#define PCH_IEEE1588_ETH	(1 << 0)
    106#define PCH_IEEE1588_CAN	(1 << 1)
    107
    108/*
    109 * struct pch_dev - Driver private data
    110 */
    111struct pch_dev {
    112	struct pch_ts_regs __iomem *regs;
    113	struct ptp_clock *ptp_clock;
    114	struct ptp_clock_info caps;
    115	int exts0_enabled;
    116	int exts1_enabled;
    117
    118	u32 irq;
    119	struct pci_dev *pdev;
    120	spinlock_t register_lock;
    121};
    122
    123/*
    124 * struct pch_params - 1588 module parameter
    125 */
    126struct pch_params {
    127	u8 station[STATION_ADDR_LEN];
    128};
    129
    130/* structure to hold the module parameters */
    131static struct pch_params pch_param = {
    132	"00:00:00:00:00:00"
    133};
    134
    135/*
    136 * Register access functions
    137 */
    138static inline void pch_eth_enable_set(struct pch_dev *chip)
    139{
    140	u32 val;
    141	/* SET the eth_enable bit */
    142	val = ioread32(&chip->regs->ts_sel) | (PCH_ECS_ETH);
    143	iowrite32(val, (&chip->regs->ts_sel));
    144}
    145
    146static u64 pch_systime_read(struct pch_ts_regs __iomem *regs)
    147{
    148	u64 ns;
    149
    150	ns = ioread64_lo_hi(&regs->systime_lo);
    151
    152	return ns << TICKS_NS_SHIFT;
    153}
    154
    155static void pch_systime_write(struct pch_ts_regs __iomem *regs, u64 ns)
    156{
    157	iowrite64_lo_hi(ns >> TICKS_NS_SHIFT, &regs->systime_lo);
    158}
    159
    160static inline void pch_block_reset(struct pch_dev *chip)
    161{
    162	u32 val;
    163	/* Reset Hardware Assist block */
    164	val = ioread32(&chip->regs->control) | PCH_TSC_RESET;
    165	iowrite32(val, (&chip->regs->control));
    166	val = val & ~PCH_TSC_RESET;
    167	iowrite32(val, (&chip->regs->control));
    168}
    169
    170void pch_ch_control_write(struct pci_dev *pdev, u32 val)
    171{
    172	struct pch_dev *chip = pci_get_drvdata(pdev);
    173
    174	iowrite32(val, (&chip->regs->ch_control));
    175}
    176EXPORT_SYMBOL(pch_ch_control_write);
    177
    178u32 pch_ch_event_read(struct pci_dev *pdev)
    179{
    180	struct pch_dev *chip = pci_get_drvdata(pdev);
    181	u32 val;
    182
    183	val = ioread32(&chip->regs->ch_event);
    184
    185	return val;
    186}
    187EXPORT_SYMBOL(pch_ch_event_read);
    188
    189void pch_ch_event_write(struct pci_dev *pdev, u32 val)
    190{
    191	struct pch_dev *chip = pci_get_drvdata(pdev);
    192
    193	iowrite32(val, (&chip->regs->ch_event));
    194}
    195EXPORT_SYMBOL(pch_ch_event_write);
    196
    197u32 pch_src_uuid_lo_read(struct pci_dev *pdev)
    198{
    199	struct pch_dev *chip = pci_get_drvdata(pdev);
    200	u32 val;
    201
    202	val = ioread32(&chip->regs->src_uuid_lo);
    203
    204	return val;
    205}
    206EXPORT_SYMBOL(pch_src_uuid_lo_read);
    207
    208u32 pch_src_uuid_hi_read(struct pci_dev *pdev)
    209{
    210	struct pch_dev *chip = pci_get_drvdata(pdev);
    211	u32 val;
    212
    213	val = ioread32(&chip->regs->src_uuid_hi);
    214
    215	return val;
    216}
    217EXPORT_SYMBOL(pch_src_uuid_hi_read);
    218
    219u64 pch_rx_snap_read(struct pci_dev *pdev)
    220{
    221	struct pch_dev *chip = pci_get_drvdata(pdev);
    222	u64 ns;
    223
    224	ns = ioread64_lo_hi(&chip->regs->rx_snap_lo);
    225
    226	return ns << TICKS_NS_SHIFT;
    227}
    228EXPORT_SYMBOL(pch_rx_snap_read);
    229
    230u64 pch_tx_snap_read(struct pci_dev *pdev)
    231{
    232	struct pch_dev *chip = pci_get_drvdata(pdev);
    233	u64 ns;
    234
    235	ns = ioread64_lo_hi(&chip->regs->tx_snap_lo);
    236
    237	return ns << TICKS_NS_SHIFT;
    238}
    239EXPORT_SYMBOL(pch_tx_snap_read);
    240
    241/* This function enables all 64 bits in system time registers [high & low].
    242This is a work-around for non continuous value in the SystemTime Register*/
    243static void pch_set_system_time_count(struct pch_dev *chip)
    244{
    245	iowrite32(0x01, &chip->regs->stl_max_set_en);
    246	iowrite32(0xFFFFFFFF, &chip->regs->stl_max_set);
    247	iowrite32(0x00, &chip->regs->stl_max_set_en);
    248}
    249
    250static void pch_reset(struct pch_dev *chip)
    251{
    252	/* Reset Hardware Assist */
    253	pch_block_reset(chip);
    254
    255	/* enable all 32 bits in system time registers */
    256	pch_set_system_time_count(chip);
    257}
    258
    259/**
    260 * pch_set_station_address() - This API sets the station address used by
    261 *				    IEEE 1588 hardware when looking at PTP
    262 *				    traffic on the  ethernet interface
    263 * @addr:	dress which contain the column separated address to be used.
    264 * @pdev:	PCI device.
    265 */
    266int pch_set_station_address(u8 *addr, struct pci_dev *pdev)
    267{
    268	struct pch_dev *chip = pci_get_drvdata(pdev);
    269	bool valid;
    270	u64 mac;
    271
    272	/* Verify the parameter */
    273	if ((chip->regs == NULL) || addr == (u8 *)NULL) {
    274		dev_err(&pdev->dev,
    275			"invalid params returning PCH_INVALIDPARAM\n");
    276		return PCH_INVALIDPARAM;
    277	}
    278
    279	valid = mac_pton(addr, (u8 *)&mac);
    280	if (!valid) {
    281		dev_err(&pdev->dev, "invalid params returning PCH_INVALIDPARAM\n");
    282		return PCH_INVALIDPARAM;
    283	}
    284
    285	dev_dbg(&pdev->dev, "invoking pch_station_set\n");
    286	iowrite64_lo_hi(mac, &chip->regs->ts_st);
    287	return 0;
    288}
    289EXPORT_SYMBOL(pch_set_station_address);
    290
    291/*
    292 * Interrupt service routine
    293 */
    294static irqreturn_t isr(int irq, void *priv)
    295{
    296	struct pch_dev *pch_dev = priv;
    297	struct pch_ts_regs __iomem *regs = pch_dev->regs;
    298	struct ptp_clock_event event;
    299	u32 ack = 0, val;
    300
    301	val = ioread32(&regs->event);
    302
    303	if (val & PCH_TSE_SNS) {
    304		ack |= PCH_TSE_SNS;
    305		if (pch_dev->exts0_enabled) {
    306			event.type = PTP_CLOCK_EXTTS;
    307			event.index = 0;
    308			event.timestamp = ioread64_hi_lo(&regs->asms_hi);
    309			event.timestamp <<= TICKS_NS_SHIFT;
    310			ptp_clock_event(pch_dev->ptp_clock, &event);
    311		}
    312	}
    313
    314	if (val & PCH_TSE_SNM) {
    315		ack |= PCH_TSE_SNM;
    316		if (pch_dev->exts1_enabled) {
    317			event.type = PTP_CLOCK_EXTTS;
    318			event.index = 1;
    319			event.timestamp = ioread64_hi_lo(&regs->asms_hi);
    320			event.timestamp <<= TICKS_NS_SHIFT;
    321			ptp_clock_event(pch_dev->ptp_clock, &event);
    322		}
    323	}
    324
    325	if (val & PCH_TSE_TTIPEND)
    326		ack |= PCH_TSE_TTIPEND; /* this bit seems to be always set */
    327
    328	if (ack) {
    329		iowrite32(ack, &regs->event);
    330		return IRQ_HANDLED;
    331	} else
    332		return IRQ_NONE;
    333}
    334
    335/*
    336 * PTP clock operations
    337 */
    338
    339static int ptp_pch_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
    340{
    341	u64 adj;
    342	u32 diff, addend;
    343	int neg_adj = 0;
    344	struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
    345	struct pch_ts_regs __iomem *regs = pch_dev->regs;
    346
    347	if (ppb < 0) {
    348		neg_adj = 1;
    349		ppb = -ppb;
    350	}
    351	addend = DEFAULT_ADDEND;
    352	adj = addend;
    353	adj *= ppb;
    354	diff = div_u64(adj, 1000000000ULL);
    355
    356	addend = neg_adj ? addend - diff : addend + diff;
    357
    358	iowrite32(addend, &regs->addend);
    359
    360	return 0;
    361}
    362
    363static int ptp_pch_adjtime(struct ptp_clock_info *ptp, s64 delta)
    364{
    365	s64 now;
    366	unsigned long flags;
    367	struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
    368	struct pch_ts_regs __iomem *regs = pch_dev->regs;
    369
    370	spin_lock_irqsave(&pch_dev->register_lock, flags);
    371	now = pch_systime_read(regs);
    372	now += delta;
    373	pch_systime_write(regs, now);
    374	spin_unlock_irqrestore(&pch_dev->register_lock, flags);
    375
    376	return 0;
    377}
    378
    379static int ptp_pch_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
    380{
    381	u64 ns;
    382	unsigned long flags;
    383	struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
    384	struct pch_ts_regs __iomem *regs = pch_dev->regs;
    385
    386	spin_lock_irqsave(&pch_dev->register_lock, flags);
    387	ns = pch_systime_read(regs);
    388	spin_unlock_irqrestore(&pch_dev->register_lock, flags);
    389
    390	*ts = ns_to_timespec64(ns);
    391	return 0;
    392}
    393
    394static int ptp_pch_settime(struct ptp_clock_info *ptp,
    395			   const struct timespec64 *ts)
    396{
    397	u64 ns;
    398	unsigned long flags;
    399	struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
    400	struct pch_ts_regs __iomem *regs = pch_dev->regs;
    401
    402	ns = timespec64_to_ns(ts);
    403
    404	spin_lock_irqsave(&pch_dev->register_lock, flags);
    405	pch_systime_write(regs, ns);
    406	spin_unlock_irqrestore(&pch_dev->register_lock, flags);
    407
    408	return 0;
    409}
    410
    411static int ptp_pch_enable(struct ptp_clock_info *ptp,
    412			  struct ptp_clock_request *rq, int on)
    413{
    414	struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
    415
    416	switch (rq->type) {
    417	case PTP_CLK_REQ_EXTTS:
    418		switch (rq->extts.index) {
    419		case 0:
    420			pch_dev->exts0_enabled = on ? 1 : 0;
    421			break;
    422		case 1:
    423			pch_dev->exts1_enabled = on ? 1 : 0;
    424			break;
    425		default:
    426			return -EINVAL;
    427		}
    428		return 0;
    429	default:
    430		break;
    431	}
    432
    433	return -EOPNOTSUPP;
    434}
    435
    436static const struct ptp_clock_info ptp_pch_caps = {
    437	.owner		= THIS_MODULE,
    438	.name		= "PCH timer",
    439	.max_adj	= 50000000,
    440	.n_ext_ts	= N_EXT_TS,
    441	.n_pins		= 0,
    442	.pps		= 0,
    443	.adjfreq	= ptp_pch_adjfreq,
    444	.adjtime	= ptp_pch_adjtime,
    445	.gettime64	= ptp_pch_gettime,
    446	.settime64	= ptp_pch_settime,
    447	.enable		= ptp_pch_enable,
    448};
    449
    450static void pch_remove(struct pci_dev *pdev)
    451{
    452	struct pch_dev *chip = pci_get_drvdata(pdev);
    453
    454	free_irq(pdev->irq, chip);
    455	ptp_clock_unregister(chip->ptp_clock);
    456}
    457
    458static s32
    459pch_probe(struct pci_dev *pdev, const struct pci_device_id *id)
    460{
    461	s32 ret;
    462	unsigned long flags;
    463	struct pch_dev *chip;
    464
    465	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
    466	if (chip == NULL)
    467		return -ENOMEM;
    468
    469	/* enable the 1588 pci device */
    470	ret = pcim_enable_device(pdev);
    471	if (ret != 0) {
    472		dev_err(&pdev->dev, "could not enable the pci device\n");
    473		return ret;
    474	}
    475
    476	ret = pcim_iomap_regions(pdev, BIT(IO_MEM_BAR), "1588_regs");
    477	if (ret) {
    478		dev_err(&pdev->dev, "could not locate IO memory address\n");
    479		return ret;
    480	}
    481
    482	/* get the virtual address to the 1588 registers */
    483	chip->regs = pcim_iomap_table(pdev)[IO_MEM_BAR];
    484	chip->caps = ptp_pch_caps;
    485	chip->ptp_clock = ptp_clock_register(&chip->caps, &pdev->dev);
    486	if (IS_ERR(chip->ptp_clock))
    487		return PTR_ERR(chip->ptp_clock);
    488
    489	spin_lock_init(&chip->register_lock);
    490
    491	ret = request_irq(pdev->irq, &isr, IRQF_SHARED, KBUILD_MODNAME, chip);
    492	if (ret != 0) {
    493		dev_err(&pdev->dev, "failed to get irq %d\n", pdev->irq);
    494		goto err_req_irq;
    495	}
    496
    497	/* indicate success */
    498	chip->irq = pdev->irq;
    499	chip->pdev = pdev;
    500	pci_set_drvdata(pdev, chip);
    501
    502	spin_lock_irqsave(&chip->register_lock, flags);
    503	/* reset the ieee1588 h/w */
    504	pch_reset(chip);
    505
    506	iowrite32(DEFAULT_ADDEND, &chip->regs->addend);
    507	iowrite64_lo_hi(1, &chip->regs->trgt_lo);
    508	iowrite32(PCH_TSE_TTIPEND, &chip->regs->event);
    509
    510	pch_eth_enable_set(chip);
    511
    512	if (strcmp(pch_param.station, "00:00:00:00:00:00") != 0) {
    513		if (pch_set_station_address(pch_param.station, pdev) != 0) {
    514			dev_err(&pdev->dev,
    515			"Invalid station address parameter\n"
    516			"Module loaded but station address not set correctly\n"
    517			);
    518		}
    519	}
    520	spin_unlock_irqrestore(&chip->register_lock, flags);
    521	return 0;
    522
    523err_req_irq:
    524	ptp_clock_unregister(chip->ptp_clock);
    525
    526	dev_err(&pdev->dev, "probe failed(ret=0x%x)\n", ret);
    527
    528	return ret;
    529}
    530
    531static const struct pci_device_id pch_ieee1588_pcidev_id[] = {
    532	{
    533	  .vendor = PCI_VENDOR_ID_INTEL,
    534	  .device = PCI_DEVICE_ID_PCH_1588
    535	 },
    536	{0}
    537};
    538MODULE_DEVICE_TABLE(pci, pch_ieee1588_pcidev_id);
    539
    540static struct pci_driver pch_driver = {
    541	.name = KBUILD_MODNAME,
    542	.id_table = pch_ieee1588_pcidev_id,
    543	.probe = pch_probe,
    544	.remove = pch_remove,
    545};
    546module_pci_driver(pch_driver);
    547
    548module_param_string(station,
    549		    pch_param.station, sizeof(pch_param.station), 0444);
    550MODULE_PARM_DESC(station,
    551	 "IEEE 1588 station address to use - colon separated hex values");
    552
    553MODULE_AUTHOR("LAPIS SEMICONDUCTOR, <tshimizu818@gmail.com>");
    554MODULE_DESCRIPTION("PTP clock using the EG20T timer");
    555MODULE_LICENSE("GPL");