162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license.  When using or
362306a36Sopenharmony_ci *   redistributing this file, you may do so under either license.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *   GPL LICENSE SUMMARY
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *   Copyright (C) 2016 Advanced Micro Devices, Inc. All Rights Reserved.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *   This program is free software; you can redistribute it and/or modify
1062306a36Sopenharmony_ci *   it under the terms of version 2 of the GNU General Public License as
1162306a36Sopenharmony_ci *   published by the Free Software Foundation.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci *   BSD LICENSE
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci *   Copyright (C) 2016 Advanced Micro Devices, Inc. All Rights Reserved.
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci *   Redistribution and use in source and binary forms, with or without
1862306a36Sopenharmony_ci *   modification, are permitted provided that the following conditions
1962306a36Sopenharmony_ci *   are met:
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci *     * Redistributions of source code must retain the above copyright
2262306a36Sopenharmony_ci *       notice, this list of conditions and the following disclaimer.
2362306a36Sopenharmony_ci *     * Redistributions in binary form must reproduce the above copy
2462306a36Sopenharmony_ci *       notice, this list of conditions and the following disclaimer in
2562306a36Sopenharmony_ci *       the documentation and/or other materials provided with the
2662306a36Sopenharmony_ci *       distribution.
2762306a36Sopenharmony_ci *     * Neither the name of AMD Corporation nor the names of its
2862306a36Sopenharmony_ci *       contributors may be used to endorse or promote products derived
2962306a36Sopenharmony_ci *       from this software without specific prior written permission.
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3262306a36Sopenharmony_ci *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3362306a36Sopenharmony_ci *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3462306a36Sopenharmony_ci *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3562306a36Sopenharmony_ci *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3662306a36Sopenharmony_ci *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3762306a36Sopenharmony_ci *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3862306a36Sopenharmony_ci *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3962306a36Sopenharmony_ci *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4062306a36Sopenharmony_ci *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4162306a36Sopenharmony_ci *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * AMD PCIe NTB Linux driver
4462306a36Sopenharmony_ci *
4562306a36Sopenharmony_ci * Contact Information:
4662306a36Sopenharmony_ci * Xiangliang Yu <Xiangliang.Yu@amd.com>
4762306a36Sopenharmony_ci */
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#ifndef NTB_HW_AMD_H
5062306a36Sopenharmony_ci#define NTB_HW_AMD_H
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#include <linux/ntb.h>
5362306a36Sopenharmony_ci#include <linux/pci.h>
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define AMD_LINK_HB_TIMEOUT	msecs_to_jiffies(1000)
5662306a36Sopenharmony_ci#define NTB_LNK_STA_SPEED_MASK	0x000F0000
5762306a36Sopenharmony_ci#define NTB_LNK_STA_WIDTH_MASK	0x03F00000
5862306a36Sopenharmony_ci#define NTB_LNK_STA_SPEED(x)	(((x) & NTB_LNK_STA_SPEED_MASK) >> 16)
5962306a36Sopenharmony_ci#define NTB_LNK_STA_WIDTH(x)	(((x) & NTB_LNK_STA_WIDTH_MASK) >> 20)
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#ifndef read64
6262306a36Sopenharmony_ci#ifdef readq
6362306a36Sopenharmony_ci#define read64 readq
6462306a36Sopenharmony_ci#else
6562306a36Sopenharmony_ci#define read64 _read64
6662306a36Sopenharmony_cistatic inline u64 _read64(void __iomem *mmio)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	u64 low, high;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	low = readl(mmio);
7162306a36Sopenharmony_ci	high = readl(mmio + sizeof(u32));
7262306a36Sopenharmony_ci	return low | (high << 32);
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci#endif
7562306a36Sopenharmony_ci#endif
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci#ifndef write64
7862306a36Sopenharmony_ci#ifdef writeq
7962306a36Sopenharmony_ci#define write64 writeq
8062306a36Sopenharmony_ci#else
8162306a36Sopenharmony_ci#define write64 _write64
8262306a36Sopenharmony_cistatic inline void _write64(u64 val, void __iomem *mmio)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	writel(val, mmio);
8562306a36Sopenharmony_ci	writel(val >> 32, mmio + sizeof(u32));
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci#endif
8862306a36Sopenharmony_ci#endif
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cienum {
9162306a36Sopenharmony_ci	/* AMD NTB Capability */
9262306a36Sopenharmony_ci	AMD_DB_CNT		= 16,
9362306a36Sopenharmony_ci	AMD_MSIX_VECTOR_CNT	= 24,
9462306a36Sopenharmony_ci	AMD_SPADS_CNT		= 16,
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	/*  AMD NTB register offset */
9762306a36Sopenharmony_ci	AMD_CNTL_OFFSET		= 0x200,
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	/* NTB control register bits */
10062306a36Sopenharmony_ci	PMM_REG_CTL		= BIT(21),
10162306a36Sopenharmony_ci	SMM_REG_CTL		= BIT(20),
10262306a36Sopenharmony_ci	SMM_REG_ACC_PATH	= BIT(18),
10362306a36Sopenharmony_ci	PMM_REG_ACC_PATH	= BIT(17),
10462306a36Sopenharmony_ci	NTB_CLK_EN		= BIT(16),
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	AMD_STA_OFFSET		= 0x204,
10762306a36Sopenharmony_ci	AMD_PGSLV_OFFSET	= 0x208,
10862306a36Sopenharmony_ci	AMD_SPAD_MUX_OFFSET	= 0x20C,
10962306a36Sopenharmony_ci	AMD_SPAD_OFFSET		= 0x210,
11062306a36Sopenharmony_ci	AMD_RSMU_HCID		= 0x250,
11162306a36Sopenharmony_ci	AMD_RSMU_SIID		= 0x254,
11262306a36Sopenharmony_ci	AMD_PSION_OFFSET	= 0x300,
11362306a36Sopenharmony_ci	AMD_SSION_OFFSET	= 0x330,
11462306a36Sopenharmony_ci	AMD_MMINDEX_OFFSET	= 0x400,
11562306a36Sopenharmony_ci	AMD_MMDATA_OFFSET	= 0x404,
11662306a36Sopenharmony_ci	AMD_SIDEINFO_OFFSET	= 0x408,
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	AMD_SIDE_MASK		= BIT(0),
11962306a36Sopenharmony_ci	AMD_SIDE_READY		= BIT(1),
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	/* limit register */
12262306a36Sopenharmony_ci	AMD_ROMBARLMT_OFFSET	= 0x410,
12362306a36Sopenharmony_ci	AMD_BAR1LMT_OFFSET	= 0x414,
12462306a36Sopenharmony_ci	AMD_BAR23LMT_OFFSET	= 0x418,
12562306a36Sopenharmony_ci	AMD_BAR45LMT_OFFSET	= 0x420,
12662306a36Sopenharmony_ci	/* xlat address */
12762306a36Sopenharmony_ci	AMD_POMBARXLAT_OFFSET	= 0x428,
12862306a36Sopenharmony_ci	AMD_BAR1XLAT_OFFSET	= 0x430,
12962306a36Sopenharmony_ci	AMD_BAR23XLAT_OFFSET	= 0x438,
13062306a36Sopenharmony_ci	AMD_BAR45XLAT_OFFSET	= 0x440,
13162306a36Sopenharmony_ci	/* doorbell and interrupt */
13262306a36Sopenharmony_ci	AMD_DBFM_OFFSET		= 0x450,
13362306a36Sopenharmony_ci	AMD_DBREQ_OFFSET	= 0x454,
13462306a36Sopenharmony_ci	AMD_MIRRDBSTAT_OFFSET	= 0x458,
13562306a36Sopenharmony_ci	AMD_DBMASK_OFFSET	= 0x45C,
13662306a36Sopenharmony_ci	AMD_DBSTAT_OFFSET	= 0x460,
13762306a36Sopenharmony_ci	AMD_INTMASK_OFFSET	= 0x470,
13862306a36Sopenharmony_ci	AMD_INTSTAT_OFFSET	= 0x474,
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	/* event type */
14162306a36Sopenharmony_ci	AMD_PEER_FLUSH_EVENT	= BIT(0),
14262306a36Sopenharmony_ci	AMD_PEER_RESET_EVENT	= BIT(1),
14362306a36Sopenharmony_ci	AMD_PEER_D3_EVENT	= BIT(2),
14462306a36Sopenharmony_ci	AMD_PEER_PMETO_EVENT	= BIT(3),
14562306a36Sopenharmony_ci	AMD_PEER_D0_EVENT	= BIT(4),
14662306a36Sopenharmony_ci	AMD_LINK_UP_EVENT	= BIT(5),
14762306a36Sopenharmony_ci	AMD_LINK_DOWN_EVENT	= BIT(6),
14862306a36Sopenharmony_ci	AMD_EVENT_INTMASK	= (AMD_PEER_FLUSH_EVENT |
14962306a36Sopenharmony_ci				AMD_PEER_RESET_EVENT | AMD_PEER_D3_EVENT |
15062306a36Sopenharmony_ci				AMD_PEER_PMETO_EVENT | AMD_PEER_D0_EVENT |
15162306a36Sopenharmony_ci				AMD_LINK_UP_EVENT | AMD_LINK_DOWN_EVENT),
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	AMD_PMESTAT_OFFSET	= 0x480,
15462306a36Sopenharmony_ci	AMD_PMSGTRIG_OFFSET	= 0x490,
15562306a36Sopenharmony_ci	AMD_LTRLATENCY_OFFSET	= 0x494,
15662306a36Sopenharmony_ci	AMD_FLUSHTRIG_OFFSET	= 0x498,
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	/* SMU register*/
15962306a36Sopenharmony_ci	AMD_SMUACK_OFFSET	= 0x4A0,
16062306a36Sopenharmony_ci	AMD_SINRST_OFFSET	= 0x4A4,
16162306a36Sopenharmony_ci	AMD_RSPNUM_OFFSET	= 0x4A8,
16262306a36Sopenharmony_ci	AMD_SMU_SPADMUTEX	= 0x4B0,
16362306a36Sopenharmony_ci	AMD_SMU_SPADOFFSET	= 0x4B4,
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	AMD_PEER_OFFSET		= 0x400,
16662306a36Sopenharmony_ci};
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistruct ntb_dev_data {
16962306a36Sopenharmony_ci	const unsigned char mw_count;
17062306a36Sopenharmony_ci	const unsigned int mw_idx;
17162306a36Sopenharmony_ci};
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cistruct amd_ntb_dev;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_cistruct amd_ntb_vec {
17662306a36Sopenharmony_ci	struct amd_ntb_dev	*ndev;
17762306a36Sopenharmony_ci	int			num;
17862306a36Sopenharmony_ci};
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistruct amd_ntb_dev {
18162306a36Sopenharmony_ci	struct ntb_dev ntb;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	u32 ntb_side;
18462306a36Sopenharmony_ci	u32 lnk_sta;
18562306a36Sopenharmony_ci	u32 cntl_sta;
18662306a36Sopenharmony_ci	u32 peer_sta;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	struct ntb_dev_data *dev_data;
18962306a36Sopenharmony_ci	unsigned char mw_count;
19062306a36Sopenharmony_ci	unsigned char spad_count;
19162306a36Sopenharmony_ci	unsigned char db_count;
19262306a36Sopenharmony_ci	unsigned char msix_vec_count;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	u64 db_valid_mask;
19562306a36Sopenharmony_ci	u64 db_mask;
19662306a36Sopenharmony_ci	u64 db_last_bit;
19762306a36Sopenharmony_ci	u32 int_mask;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	struct msix_entry *msix;
20062306a36Sopenharmony_ci	struct amd_ntb_vec *vec;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	/* synchronize rmw access of db_mask and hw reg */
20362306a36Sopenharmony_ci	spinlock_t db_mask_lock;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	void __iomem *self_mmio;
20662306a36Sopenharmony_ci	void __iomem *peer_mmio;
20762306a36Sopenharmony_ci	unsigned int self_spad;
20862306a36Sopenharmony_ci	unsigned int peer_spad;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	struct delayed_work hb_timer;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	struct dentry *debugfs_dir;
21362306a36Sopenharmony_ci	struct dentry *debugfs_info;
21462306a36Sopenharmony_ci};
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci#define ntb_ndev(__ntb) container_of(__ntb, struct amd_ntb_dev, ntb)
21762306a36Sopenharmony_ci#define hb_ndev(__work) container_of(__work, struct amd_ntb_dev, hb_timer.work)
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_cistatic void amd_set_side_info_reg(struct amd_ntb_dev *ndev, bool peer);
22062306a36Sopenharmony_cistatic void amd_clear_side_info_reg(struct amd_ntb_dev *ndev, bool peer);
22162306a36Sopenharmony_cistatic int amd_poll_link(struct amd_ntb_dev *ndev);
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci#endif
224