xref: /dpdk/drivers/raw/ifpga/base/ifpga_fme.c (revision b6e029cfa4ad1bca4244e81d23835406e54fa352)
1473c88f9SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2473c88f9SBruce Richardson  * Copyright(c) 2010-2018 Intel Corporation
3473c88f9SBruce Richardson  */
4473c88f9SBruce Richardson 
5473c88f9SBruce Richardson #include "ifpga_feature_dev.h"
6473c88f9SBruce Richardson #include "opae_spi.h"
7473c88f9SBruce Richardson #include "opae_intel_max10.h"
8473c88f9SBruce Richardson #include "opae_i2c.h"
9473c88f9SBruce Richardson #include "opae_at24_eeprom.h"
10a05bd1b4SWei Huang #include "ifpga_sec_mgr.h"
11473c88f9SBruce Richardson 
12473c88f9SBruce Richardson #define PWR_THRESHOLD_MAX       0x7F
13473c88f9SBruce Richardson 
fme_get_prop(struct ifpga_fme_hw * fme,struct feature_prop * prop)14473c88f9SBruce Richardson int fme_get_prop(struct ifpga_fme_hw *fme, struct feature_prop *prop)
15473c88f9SBruce Richardson {
16473c88f9SBruce Richardson 	struct ifpga_feature *feature;
17473c88f9SBruce Richardson 
18473c88f9SBruce Richardson 	if (!fme)
19473c88f9SBruce Richardson 		return -ENOENT;
20473c88f9SBruce Richardson 
21473c88f9SBruce Richardson 	feature = get_fme_feature_by_id(fme, prop->feature_id);
22473c88f9SBruce Richardson 
23473c88f9SBruce Richardson 	if (feature && feature->ops && feature->ops->get_prop)
24473c88f9SBruce Richardson 		return feature->ops->get_prop(feature, prop);
25473c88f9SBruce Richardson 
26473c88f9SBruce Richardson 	return -ENOENT;
27473c88f9SBruce Richardson }
28473c88f9SBruce Richardson 
fme_set_prop(struct ifpga_fme_hw * fme,struct feature_prop * prop)29473c88f9SBruce Richardson int fme_set_prop(struct ifpga_fme_hw *fme, struct feature_prop *prop)
30473c88f9SBruce Richardson {
31473c88f9SBruce Richardson 	struct ifpga_feature *feature;
32473c88f9SBruce Richardson 
33473c88f9SBruce Richardson 	if (!fme)
34473c88f9SBruce Richardson 		return -ENOENT;
35473c88f9SBruce Richardson 
36473c88f9SBruce Richardson 	feature = get_fme_feature_by_id(fme, prop->feature_id);
37473c88f9SBruce Richardson 
38473c88f9SBruce Richardson 	if (feature && feature->ops && feature->ops->set_prop)
39473c88f9SBruce Richardson 		return feature->ops->set_prop(feature, prop);
40473c88f9SBruce Richardson 
41473c88f9SBruce Richardson 	return -ENOENT;
42473c88f9SBruce Richardson }
43473c88f9SBruce Richardson 
fme_set_irq(struct ifpga_fme_hw * fme,u32 feature_id,void * irq_set)44473c88f9SBruce Richardson int fme_set_irq(struct ifpga_fme_hw *fme, u32 feature_id, void *irq_set)
45473c88f9SBruce Richardson {
46473c88f9SBruce Richardson 	struct ifpga_feature *feature;
47473c88f9SBruce Richardson 
48473c88f9SBruce Richardson 	if (!fme)
49473c88f9SBruce Richardson 		return -ENOENT;
50473c88f9SBruce Richardson 
51473c88f9SBruce Richardson 	feature = get_fme_feature_by_id(fme, feature_id);
52473c88f9SBruce Richardson 
53473c88f9SBruce Richardson 	if (feature && feature->ops && feature->ops->set_irq)
54473c88f9SBruce Richardson 		return feature->ops->set_irq(feature, irq_set);
55473c88f9SBruce Richardson 
56473c88f9SBruce Richardson 	return -ENOENT;
57473c88f9SBruce Richardson }
58473c88f9SBruce Richardson 
59473c88f9SBruce Richardson /* fme private feature head */
fme_hdr_init(struct ifpga_feature * feature)60473c88f9SBruce Richardson static int fme_hdr_init(struct ifpga_feature *feature)
61473c88f9SBruce Richardson {
62473c88f9SBruce Richardson 	struct feature_fme_header *fme_hdr;
63473c88f9SBruce Richardson 
64473c88f9SBruce Richardson 	fme_hdr = (struct feature_fme_header *)feature->addr;
65473c88f9SBruce Richardson 
66473c88f9SBruce Richardson 	dev_info(NULL, "FME HDR Init.\n");
67473c88f9SBruce Richardson 	dev_info(NULL, "FME cap %llx.\n",
68473c88f9SBruce Richardson 		 (unsigned long long)fme_hdr->capability.csr);
69473c88f9SBruce Richardson 
70473c88f9SBruce Richardson 	return 0;
71473c88f9SBruce Richardson }
72473c88f9SBruce Richardson 
fme_hdr_uinit(struct ifpga_feature * feature)73473c88f9SBruce Richardson static void fme_hdr_uinit(struct ifpga_feature *feature)
74473c88f9SBruce Richardson {
75473c88f9SBruce Richardson 	UNUSED(feature);
76473c88f9SBruce Richardson 
77473c88f9SBruce Richardson 	dev_info(NULL, "FME HDR UInit.\n");
78473c88f9SBruce Richardson }
79473c88f9SBruce Richardson 
fme_hdr_get_revision(struct ifpga_fme_hw * fme,u64 * revision)80473c88f9SBruce Richardson static int fme_hdr_get_revision(struct ifpga_fme_hw *fme, u64 *revision)
81473c88f9SBruce Richardson {
82473c88f9SBruce Richardson 	struct feature_fme_header *fme_hdr
83473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER);
84473c88f9SBruce Richardson 	struct feature_header header;
85473c88f9SBruce Richardson 
86473c88f9SBruce Richardson 	header.csr = readq(&fme_hdr->header);
87473c88f9SBruce Richardson 	*revision = header.revision;
88473c88f9SBruce Richardson 
89473c88f9SBruce Richardson 	return 0;
90473c88f9SBruce Richardson }
91473c88f9SBruce Richardson 
fme_hdr_get_ports_num(struct ifpga_fme_hw * fme,u64 * ports_num)92473c88f9SBruce Richardson static int fme_hdr_get_ports_num(struct ifpga_fme_hw *fme, u64 *ports_num)
93473c88f9SBruce Richardson {
94473c88f9SBruce Richardson 	struct feature_fme_header *fme_hdr
95473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER);
96473c88f9SBruce Richardson 	struct feature_fme_capability fme_capability;
97473c88f9SBruce Richardson 
98473c88f9SBruce Richardson 	fme_capability.csr = readq(&fme_hdr->capability);
99473c88f9SBruce Richardson 	*ports_num = fme_capability.num_ports;
100473c88f9SBruce Richardson 
101473c88f9SBruce Richardson 	return 0;
102473c88f9SBruce Richardson }
103473c88f9SBruce Richardson 
fme_hdr_get_port_type(struct ifpga_fme_hw * fme,u64 * port_type)104cf38bcd7SWei Huang static int fme_hdr_get_port_type(struct ifpga_fme_hw *fme, u64 *port_type)
105cf38bcd7SWei Huang {
106cf38bcd7SWei Huang 	struct feature_fme_header *fme_hdr
107cf38bcd7SWei Huang 		= get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER);
108cf38bcd7SWei Huang 	struct feature_fme_port pt;
109cf38bcd7SWei Huang 	u32 port = (u32)((*port_type >> 32) & 0xffffffff);
110cf38bcd7SWei Huang 
111cf38bcd7SWei Huang 	pt.csr = readq(&fme_hdr->port[port]);
112cf38bcd7SWei Huang 	if (!pt.port_implemented)
113cf38bcd7SWei Huang 		return -ENODEV;
114cf38bcd7SWei Huang 	if (pt.afu_access_control)
115cf38bcd7SWei Huang 		*port_type |= 0x1;
116cf38bcd7SWei Huang 	else
117cf38bcd7SWei Huang 		*port_type &= ~0x1;
118cf38bcd7SWei Huang 
119cf38bcd7SWei Huang 	return 0;
120cf38bcd7SWei Huang }
121cf38bcd7SWei Huang 
fme_hdr_get_cache_size(struct ifpga_fme_hw * fme,u64 * cache_size)122473c88f9SBruce Richardson static int fme_hdr_get_cache_size(struct ifpga_fme_hw *fme, u64 *cache_size)
123473c88f9SBruce Richardson {
124473c88f9SBruce Richardson 	struct feature_fme_header *fme_hdr
125473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER);
126473c88f9SBruce Richardson 	struct feature_fme_capability fme_capability;
127473c88f9SBruce Richardson 
128473c88f9SBruce Richardson 	fme_capability.csr = readq(&fme_hdr->capability);
129473c88f9SBruce Richardson 	*cache_size = fme_capability.cache_size;
130473c88f9SBruce Richardson 
131473c88f9SBruce Richardson 	return 0;
132473c88f9SBruce Richardson }
133473c88f9SBruce Richardson 
fme_hdr_get_version(struct ifpga_fme_hw * fme,u64 * version)134473c88f9SBruce Richardson static int fme_hdr_get_version(struct ifpga_fme_hw *fme, u64 *version)
135473c88f9SBruce Richardson {
136473c88f9SBruce Richardson 	struct feature_fme_header *fme_hdr
137473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER);
138473c88f9SBruce Richardson 	struct feature_fme_capability fme_capability;
139473c88f9SBruce Richardson 
140473c88f9SBruce Richardson 	fme_capability.csr = readq(&fme_hdr->capability);
141473c88f9SBruce Richardson 	*version = fme_capability.fabric_verid;
142473c88f9SBruce Richardson 
143473c88f9SBruce Richardson 	return 0;
144473c88f9SBruce Richardson }
145473c88f9SBruce Richardson 
fme_hdr_get_socket_id(struct ifpga_fme_hw * fme,u64 * socket_id)146473c88f9SBruce Richardson static int fme_hdr_get_socket_id(struct ifpga_fme_hw *fme, u64 *socket_id)
147473c88f9SBruce Richardson {
148473c88f9SBruce Richardson 	struct feature_fme_header *fme_hdr
149473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER);
150473c88f9SBruce Richardson 	struct feature_fme_capability fme_capability;
151473c88f9SBruce Richardson 
152473c88f9SBruce Richardson 	fme_capability.csr = readq(&fme_hdr->capability);
153473c88f9SBruce Richardson 	*socket_id = fme_capability.socket_id;
154473c88f9SBruce Richardson 
155473c88f9SBruce Richardson 	return 0;
156473c88f9SBruce Richardson }
157473c88f9SBruce Richardson 
fme_hdr_get_bitstream_id(struct ifpga_fme_hw * fme,u64 * bitstream_id)158473c88f9SBruce Richardson static int fme_hdr_get_bitstream_id(struct ifpga_fme_hw *fme,
159473c88f9SBruce Richardson 				    u64 *bitstream_id)
160473c88f9SBruce Richardson {
161473c88f9SBruce Richardson 	struct feature_fme_header *fme_hdr
162473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER);
163473c88f9SBruce Richardson 
164473c88f9SBruce Richardson 	*bitstream_id = readq(&fme_hdr->bitstream_id);
165473c88f9SBruce Richardson 
166473c88f9SBruce Richardson 	return 0;
167473c88f9SBruce Richardson }
168473c88f9SBruce Richardson 
fme_hdr_get_bitstream_metadata(struct ifpga_fme_hw * fme,u64 * bitstream_metadata)169473c88f9SBruce Richardson static int fme_hdr_get_bitstream_metadata(struct ifpga_fme_hw *fme,
170473c88f9SBruce Richardson 					  u64 *bitstream_metadata)
171473c88f9SBruce Richardson {
172473c88f9SBruce Richardson 	struct feature_fme_header *fme_hdr
173473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER);
174473c88f9SBruce Richardson 
175473c88f9SBruce Richardson 	*bitstream_metadata = readq(&fme_hdr->bitstream_md);
176473c88f9SBruce Richardson 
177473c88f9SBruce Richardson 	return 0;
178473c88f9SBruce Richardson }
179473c88f9SBruce Richardson 
180473c88f9SBruce Richardson static int
fme_hdr_get_prop(struct ifpga_feature * feature,struct feature_prop * prop)181473c88f9SBruce Richardson fme_hdr_get_prop(struct ifpga_feature *feature, struct feature_prop *prop)
182473c88f9SBruce Richardson {
183473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = feature->parent;
184473c88f9SBruce Richardson 
185473c88f9SBruce Richardson 	switch (prop->prop_id) {
186473c88f9SBruce Richardson 	case FME_HDR_PROP_REVISION:
187473c88f9SBruce Richardson 		return fme_hdr_get_revision(fme, &prop->data);
188473c88f9SBruce Richardson 	case FME_HDR_PROP_PORTS_NUM:
189473c88f9SBruce Richardson 		return fme_hdr_get_ports_num(fme, &prop->data);
190473c88f9SBruce Richardson 	case FME_HDR_PROP_CACHE_SIZE:
191473c88f9SBruce Richardson 		return fme_hdr_get_cache_size(fme, &prop->data);
192473c88f9SBruce Richardson 	case FME_HDR_PROP_VERSION:
193473c88f9SBruce Richardson 		return fme_hdr_get_version(fme, &prop->data);
194473c88f9SBruce Richardson 	case FME_HDR_PROP_SOCKET_ID:
195473c88f9SBruce Richardson 		return fme_hdr_get_socket_id(fme, &prop->data);
196473c88f9SBruce Richardson 	case FME_HDR_PROP_BITSTREAM_ID:
197473c88f9SBruce Richardson 		return fme_hdr_get_bitstream_id(fme, &prop->data);
198473c88f9SBruce Richardson 	case FME_HDR_PROP_BITSTREAM_METADATA:
199473c88f9SBruce Richardson 		return fme_hdr_get_bitstream_metadata(fme, &prop->data);
200cf38bcd7SWei Huang 	case FME_HDR_PROP_PORT_TYPE:
201cf38bcd7SWei Huang 		return fme_hdr_get_port_type(fme, &prop->data);
202473c88f9SBruce Richardson 	}
203473c88f9SBruce Richardson 
204473c88f9SBruce Richardson 	return -ENOENT;
205473c88f9SBruce Richardson }
206473c88f9SBruce Richardson 
207473c88f9SBruce Richardson struct ifpga_feature_ops fme_hdr_ops = {
208473c88f9SBruce Richardson 	.init = fme_hdr_init,
209473c88f9SBruce Richardson 	.uinit = fme_hdr_uinit,
210473c88f9SBruce Richardson 	.get_prop = fme_hdr_get_prop,
211473c88f9SBruce Richardson };
212473c88f9SBruce Richardson 
213473c88f9SBruce Richardson /* thermal management */
fme_thermal_get_threshold1(struct ifpga_fme_hw * fme,u64 * thres1)214473c88f9SBruce Richardson static int fme_thermal_get_threshold1(struct ifpga_fme_hw *fme, u64 *thres1)
215473c88f9SBruce Richardson {
216473c88f9SBruce Richardson 	struct feature_fme_thermal *thermal;
217473c88f9SBruce Richardson 	struct feature_fme_tmp_threshold temp_threshold;
218473c88f9SBruce Richardson 
219473c88f9SBruce Richardson 	thermal = get_fme_feature_ioaddr_by_index(fme,
220473c88f9SBruce Richardson 						  FME_FEATURE_ID_THERMAL_MGMT);
221473c88f9SBruce Richardson 
222473c88f9SBruce Richardson 	temp_threshold.csr = readq(&thermal->threshold);
223473c88f9SBruce Richardson 	*thres1 = temp_threshold.tmp_thshold1;
224473c88f9SBruce Richardson 
225473c88f9SBruce Richardson 	return 0;
226473c88f9SBruce Richardson }
227473c88f9SBruce Richardson 
fme_thermal_set_threshold1(struct ifpga_fme_hw * fme,u64 thres1)228473c88f9SBruce Richardson static int fme_thermal_set_threshold1(struct ifpga_fme_hw *fme, u64 thres1)
229473c88f9SBruce Richardson {
230473c88f9SBruce Richardson 	struct feature_fme_thermal *thermal;
231473c88f9SBruce Richardson 	struct feature_fme_header *fme_hdr;
232473c88f9SBruce Richardson 	struct feature_fme_tmp_threshold tmp_threshold;
233473c88f9SBruce Richardson 	struct feature_fme_capability fme_capability;
234473c88f9SBruce Richardson 
235473c88f9SBruce Richardson 	thermal = get_fme_feature_ioaddr_by_index(fme,
236473c88f9SBruce Richardson 						  FME_FEATURE_ID_THERMAL_MGMT);
237473c88f9SBruce Richardson 	fme_hdr = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER);
238473c88f9SBruce Richardson 
239473c88f9SBruce Richardson 	spinlock_lock(&fme->lock);
240473c88f9SBruce Richardson 	tmp_threshold.csr = readq(&thermal->threshold);
241473c88f9SBruce Richardson 	fme_capability.csr = readq(&fme_hdr->capability);
242473c88f9SBruce Richardson 
243473c88f9SBruce Richardson 	if (fme_capability.lock_bit == 1) {
244473c88f9SBruce Richardson 		spinlock_unlock(&fme->lock);
245473c88f9SBruce Richardson 		return -EBUSY;
246473c88f9SBruce Richardson 	} else if (thres1 > 100) {
247473c88f9SBruce Richardson 		spinlock_unlock(&fme->lock);
248473c88f9SBruce Richardson 		return -EINVAL;
249473c88f9SBruce Richardson 	} else if (thres1 == 0) {
250473c88f9SBruce Richardson 		tmp_threshold.tmp_thshold1_enable = 0;
251473c88f9SBruce Richardson 		tmp_threshold.tmp_thshold1 = thres1;
252473c88f9SBruce Richardson 	} else {
253473c88f9SBruce Richardson 		tmp_threshold.tmp_thshold1_enable = 1;
254473c88f9SBruce Richardson 		tmp_threshold.tmp_thshold1 = thres1;
255473c88f9SBruce Richardson 	}
256473c88f9SBruce Richardson 
257473c88f9SBruce Richardson 	writeq(tmp_threshold.csr, &thermal->threshold);
258473c88f9SBruce Richardson 	spinlock_unlock(&fme->lock);
259473c88f9SBruce Richardson 
260473c88f9SBruce Richardson 	return 0;
261473c88f9SBruce Richardson }
262473c88f9SBruce Richardson 
fme_thermal_get_threshold2(struct ifpga_fme_hw * fme,u64 * thres2)263473c88f9SBruce Richardson static int fme_thermal_get_threshold2(struct ifpga_fme_hw *fme, u64 *thres2)
264473c88f9SBruce Richardson {
265473c88f9SBruce Richardson 	struct feature_fme_thermal *thermal;
266473c88f9SBruce Richardson 	struct feature_fme_tmp_threshold temp_threshold;
267473c88f9SBruce Richardson 
268473c88f9SBruce Richardson 	thermal = get_fme_feature_ioaddr_by_index(fme,
269473c88f9SBruce Richardson 						  FME_FEATURE_ID_THERMAL_MGMT);
270473c88f9SBruce Richardson 
271473c88f9SBruce Richardson 	temp_threshold.csr = readq(&thermal->threshold);
272473c88f9SBruce Richardson 	*thres2 = temp_threshold.tmp_thshold2;
273473c88f9SBruce Richardson 
274473c88f9SBruce Richardson 	return 0;
275473c88f9SBruce Richardson }
276473c88f9SBruce Richardson 
fme_thermal_set_threshold2(struct ifpga_fme_hw * fme,u64 thres2)277473c88f9SBruce Richardson static int fme_thermal_set_threshold2(struct ifpga_fme_hw *fme, u64 thres2)
278473c88f9SBruce Richardson {
279473c88f9SBruce Richardson 	struct feature_fme_thermal *thermal;
280473c88f9SBruce Richardson 	struct feature_fme_header *fme_hdr;
281473c88f9SBruce Richardson 	struct feature_fme_tmp_threshold tmp_threshold;
282473c88f9SBruce Richardson 	struct feature_fme_capability fme_capability;
283473c88f9SBruce Richardson 
284473c88f9SBruce Richardson 	thermal = get_fme_feature_ioaddr_by_index(fme,
285473c88f9SBruce Richardson 						  FME_FEATURE_ID_THERMAL_MGMT);
286473c88f9SBruce Richardson 	fme_hdr = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER);
287473c88f9SBruce Richardson 
288473c88f9SBruce Richardson 	spinlock_lock(&fme->lock);
289473c88f9SBruce Richardson 	tmp_threshold.csr = readq(&thermal->threshold);
290473c88f9SBruce Richardson 	fme_capability.csr = readq(&fme_hdr->capability);
291473c88f9SBruce Richardson 
292473c88f9SBruce Richardson 	if (fme_capability.lock_bit == 1) {
293473c88f9SBruce Richardson 		spinlock_unlock(&fme->lock);
294473c88f9SBruce Richardson 		return -EBUSY;
295473c88f9SBruce Richardson 	} else if (thres2 > 100) {
296473c88f9SBruce Richardson 		spinlock_unlock(&fme->lock);
297473c88f9SBruce Richardson 		return -EINVAL;
298473c88f9SBruce Richardson 	} else if (thres2 == 0) {
299473c88f9SBruce Richardson 		tmp_threshold.tmp_thshold2_enable = 0;
300473c88f9SBruce Richardson 		tmp_threshold.tmp_thshold2 = thres2;
301473c88f9SBruce Richardson 	} else {
302473c88f9SBruce Richardson 		tmp_threshold.tmp_thshold2_enable = 1;
303473c88f9SBruce Richardson 		tmp_threshold.tmp_thshold2 = thres2;
304473c88f9SBruce Richardson 	}
305473c88f9SBruce Richardson 
306473c88f9SBruce Richardson 	writeq(tmp_threshold.csr, &thermal->threshold);
307473c88f9SBruce Richardson 	spinlock_unlock(&fme->lock);
308473c88f9SBruce Richardson 
309473c88f9SBruce Richardson 	return 0;
310473c88f9SBruce Richardson }
311473c88f9SBruce Richardson 
fme_thermal_get_threshold_trip(struct ifpga_fme_hw * fme,u64 * thres_trip)312473c88f9SBruce Richardson static int fme_thermal_get_threshold_trip(struct ifpga_fme_hw *fme,
313473c88f9SBruce Richardson 					  u64 *thres_trip)
314473c88f9SBruce Richardson {
315473c88f9SBruce Richardson 	struct feature_fme_thermal *thermal;
316473c88f9SBruce Richardson 	struct feature_fme_tmp_threshold temp_threshold;
317473c88f9SBruce Richardson 
318473c88f9SBruce Richardson 	thermal = get_fme_feature_ioaddr_by_index(fme,
319473c88f9SBruce Richardson 						  FME_FEATURE_ID_THERMAL_MGMT);
320473c88f9SBruce Richardson 
321473c88f9SBruce Richardson 	temp_threshold.csr = readq(&thermal->threshold);
322473c88f9SBruce Richardson 	*thres_trip = temp_threshold.therm_trip_thshold;
323473c88f9SBruce Richardson 
324473c88f9SBruce Richardson 	return 0;
325473c88f9SBruce Richardson }
326473c88f9SBruce Richardson 
fme_thermal_get_threshold1_reached(struct ifpga_fme_hw * fme,u64 * thres1_reached)327473c88f9SBruce Richardson static int fme_thermal_get_threshold1_reached(struct ifpga_fme_hw *fme,
328473c88f9SBruce Richardson 					      u64 *thres1_reached)
329473c88f9SBruce Richardson {
330473c88f9SBruce Richardson 	struct feature_fme_thermal *thermal;
331473c88f9SBruce Richardson 	struct feature_fme_tmp_threshold temp_threshold;
332473c88f9SBruce Richardson 
333473c88f9SBruce Richardson 	thermal = get_fme_feature_ioaddr_by_index(fme,
334473c88f9SBruce Richardson 						  FME_FEATURE_ID_THERMAL_MGMT);
335473c88f9SBruce Richardson 
336473c88f9SBruce Richardson 	temp_threshold.csr = readq(&thermal->threshold);
337473c88f9SBruce Richardson 	*thres1_reached = temp_threshold.thshold1_status;
338473c88f9SBruce Richardson 
339473c88f9SBruce Richardson 	return 0;
340473c88f9SBruce Richardson }
341473c88f9SBruce Richardson 
fme_thermal_get_threshold2_reached(struct ifpga_fme_hw * fme,u64 * thres1_reached)342473c88f9SBruce Richardson static int fme_thermal_get_threshold2_reached(struct ifpga_fme_hw *fme,
343473c88f9SBruce Richardson 					      u64 *thres1_reached)
344473c88f9SBruce Richardson {
345473c88f9SBruce Richardson 	struct feature_fme_thermal *thermal;
346473c88f9SBruce Richardson 	struct feature_fme_tmp_threshold temp_threshold;
347473c88f9SBruce Richardson 
348473c88f9SBruce Richardson 	thermal = get_fme_feature_ioaddr_by_index(fme,
349473c88f9SBruce Richardson 						  FME_FEATURE_ID_THERMAL_MGMT);
350473c88f9SBruce Richardson 
351473c88f9SBruce Richardson 	temp_threshold.csr = readq(&thermal->threshold);
352473c88f9SBruce Richardson 	*thres1_reached = temp_threshold.thshold2_status;
353473c88f9SBruce Richardson 
354473c88f9SBruce Richardson 	return 0;
355473c88f9SBruce Richardson }
356473c88f9SBruce Richardson 
fme_thermal_get_threshold1_policy(struct ifpga_fme_hw * fme,u64 * thres1_policy)357473c88f9SBruce Richardson static int fme_thermal_get_threshold1_policy(struct ifpga_fme_hw *fme,
358473c88f9SBruce Richardson 					     u64 *thres1_policy)
359473c88f9SBruce Richardson {
360473c88f9SBruce Richardson 	struct feature_fme_thermal *thermal;
361473c88f9SBruce Richardson 	struct feature_fme_tmp_threshold temp_threshold;
362473c88f9SBruce Richardson 
363473c88f9SBruce Richardson 	thermal = get_fme_feature_ioaddr_by_index(fme,
364473c88f9SBruce Richardson 						  FME_FEATURE_ID_THERMAL_MGMT);
365473c88f9SBruce Richardson 
366473c88f9SBruce Richardson 	temp_threshold.csr = readq(&thermal->threshold);
367473c88f9SBruce Richardson 	*thres1_policy = temp_threshold.thshold_policy;
368473c88f9SBruce Richardson 
369473c88f9SBruce Richardson 	return 0;
370473c88f9SBruce Richardson }
371473c88f9SBruce Richardson 
fme_thermal_set_threshold1_policy(struct ifpga_fme_hw * fme,u64 thres1_policy)372473c88f9SBruce Richardson static int fme_thermal_set_threshold1_policy(struct ifpga_fme_hw *fme,
373473c88f9SBruce Richardson 					     u64 thres1_policy)
374473c88f9SBruce Richardson {
375473c88f9SBruce Richardson 	struct feature_fme_thermal *thermal;
376473c88f9SBruce Richardson 	struct feature_fme_tmp_threshold tmp_threshold;
377473c88f9SBruce Richardson 
378473c88f9SBruce Richardson 	thermal = get_fme_feature_ioaddr_by_index(fme,
379473c88f9SBruce Richardson 						  FME_FEATURE_ID_THERMAL_MGMT);
380473c88f9SBruce Richardson 
381473c88f9SBruce Richardson 	spinlock_lock(&fme->lock);
382473c88f9SBruce Richardson 	tmp_threshold.csr = readq(&thermal->threshold);
383473c88f9SBruce Richardson 
384473c88f9SBruce Richardson 	if (thres1_policy == 0) {
385473c88f9SBruce Richardson 		tmp_threshold.thshold_policy = 0;
386473c88f9SBruce Richardson 	} else if (thres1_policy == 1) {
387473c88f9SBruce Richardson 		tmp_threshold.thshold_policy = 1;
388473c88f9SBruce Richardson 	} else {
389473c88f9SBruce Richardson 		spinlock_unlock(&fme->lock);
390473c88f9SBruce Richardson 		return -EINVAL;
391473c88f9SBruce Richardson 	}
392473c88f9SBruce Richardson 
393473c88f9SBruce Richardson 	writeq(tmp_threshold.csr, &thermal->threshold);
394473c88f9SBruce Richardson 	spinlock_unlock(&fme->lock);
395473c88f9SBruce Richardson 
396473c88f9SBruce Richardson 	return 0;
397473c88f9SBruce Richardson }
398473c88f9SBruce Richardson 
fme_thermal_get_temperature(struct ifpga_fme_hw * fme,u64 * temp)399473c88f9SBruce Richardson static int fme_thermal_get_temperature(struct ifpga_fme_hw *fme, u64 *temp)
400473c88f9SBruce Richardson {
401473c88f9SBruce Richardson 	struct feature_fme_thermal *thermal;
402473c88f9SBruce Richardson 	struct feature_fme_temp_rdsensor_fmt1 temp_rdsensor_fmt1;
403473c88f9SBruce Richardson 
404473c88f9SBruce Richardson 	thermal = get_fme_feature_ioaddr_by_index(fme,
405473c88f9SBruce Richardson 						  FME_FEATURE_ID_THERMAL_MGMT);
406473c88f9SBruce Richardson 
407473c88f9SBruce Richardson 	temp_rdsensor_fmt1.csr = readq(&thermal->rdsensor_fm1);
408473c88f9SBruce Richardson 	*temp = temp_rdsensor_fmt1.fpga_temp;
409473c88f9SBruce Richardson 
410473c88f9SBruce Richardson 	return 0;
411473c88f9SBruce Richardson }
412473c88f9SBruce Richardson 
fme_thermal_get_revision(struct ifpga_fme_hw * fme,u64 * revision)413473c88f9SBruce Richardson static int fme_thermal_get_revision(struct ifpga_fme_hw *fme, u64 *revision)
414473c88f9SBruce Richardson {
415473c88f9SBruce Richardson 	struct feature_fme_thermal *fme_thermal
416473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
417473c88f9SBruce Richardson 						  FME_FEATURE_ID_THERMAL_MGMT);
418473c88f9SBruce Richardson 	struct feature_header header;
419473c88f9SBruce Richardson 
420473c88f9SBruce Richardson 	header.csr = readq(&fme_thermal->header);
421473c88f9SBruce Richardson 	*revision = header.revision;
422473c88f9SBruce Richardson 
423473c88f9SBruce Richardson 	return 0;
424473c88f9SBruce Richardson }
425473c88f9SBruce Richardson 
426473c88f9SBruce Richardson #define FME_THERMAL_CAP_NO_TMP_THRESHOLD	0x1
427473c88f9SBruce Richardson 
fme_thermal_mgmt_init(struct ifpga_feature * feature)428473c88f9SBruce Richardson static int fme_thermal_mgmt_init(struct ifpga_feature *feature)
429473c88f9SBruce Richardson {
430473c88f9SBruce Richardson 	struct feature_fme_thermal *fme_thermal;
431473c88f9SBruce Richardson 	struct feature_fme_tmp_threshold_cap thermal_cap;
432473c88f9SBruce Richardson 
433473c88f9SBruce Richardson 	UNUSED(feature);
434473c88f9SBruce Richardson 
435473c88f9SBruce Richardson 	dev_info(NULL, "FME thermal mgmt Init.\n");
436473c88f9SBruce Richardson 
437473c88f9SBruce Richardson 	fme_thermal = (struct feature_fme_thermal *)feature->addr;
438473c88f9SBruce Richardson 	thermal_cap.csr = readq(&fme_thermal->threshold_cap);
439473c88f9SBruce Richardson 
440473c88f9SBruce Richardson 	dev_info(NULL, "FME thermal cap %llx.\n",
441473c88f9SBruce Richardson 		 (unsigned long long)fme_thermal->threshold_cap.csr);
442473c88f9SBruce Richardson 
443473c88f9SBruce Richardson 	if (thermal_cap.tmp_thshold_disabled)
444473c88f9SBruce Richardson 		feature->cap |= FME_THERMAL_CAP_NO_TMP_THRESHOLD;
445473c88f9SBruce Richardson 
446473c88f9SBruce Richardson 	return 0;
447473c88f9SBruce Richardson }
448473c88f9SBruce Richardson 
fme_thermal_mgmt_uinit(struct ifpga_feature * feature)449473c88f9SBruce Richardson static void fme_thermal_mgmt_uinit(struct ifpga_feature *feature)
450473c88f9SBruce Richardson {
451473c88f9SBruce Richardson 	UNUSED(feature);
452473c88f9SBruce Richardson 
453473c88f9SBruce Richardson 	dev_info(NULL, "FME thermal mgmt UInit.\n");
454473c88f9SBruce Richardson }
455473c88f9SBruce Richardson 
456473c88f9SBruce Richardson static int
fme_thermal_set_prop(struct ifpga_feature * feature,struct feature_prop * prop)457473c88f9SBruce Richardson fme_thermal_set_prop(struct ifpga_feature *feature, struct feature_prop *prop)
458473c88f9SBruce Richardson {
459473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = feature->parent;
460473c88f9SBruce Richardson 
461473c88f9SBruce Richardson 	if (feature->cap & FME_THERMAL_CAP_NO_TMP_THRESHOLD)
462473c88f9SBruce Richardson 		return -ENOENT;
463473c88f9SBruce Richardson 
464473c88f9SBruce Richardson 	switch (prop->prop_id) {
465473c88f9SBruce Richardson 	case FME_THERMAL_PROP_THRESHOLD1:
466473c88f9SBruce Richardson 		return fme_thermal_set_threshold1(fme, prop->data);
467473c88f9SBruce Richardson 	case FME_THERMAL_PROP_THRESHOLD2:
468473c88f9SBruce Richardson 		return fme_thermal_set_threshold2(fme, prop->data);
469473c88f9SBruce Richardson 	case FME_THERMAL_PROP_THRESHOLD1_POLICY:
470473c88f9SBruce Richardson 		return fme_thermal_set_threshold1_policy(fme, prop->data);
471473c88f9SBruce Richardson 	}
472473c88f9SBruce Richardson 
473473c88f9SBruce Richardson 	return -ENOENT;
474473c88f9SBruce Richardson }
475473c88f9SBruce Richardson 
476473c88f9SBruce Richardson static int
fme_thermal_get_prop(struct ifpga_feature * feature,struct feature_prop * prop)477473c88f9SBruce Richardson fme_thermal_get_prop(struct ifpga_feature *feature, struct feature_prop *prop)
478473c88f9SBruce Richardson {
479473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = feature->parent;
480473c88f9SBruce Richardson 
481473c88f9SBruce Richardson 	if (feature->cap & FME_THERMAL_CAP_NO_TMP_THRESHOLD &&
482473c88f9SBruce Richardson 	    prop->prop_id != FME_THERMAL_PROP_TEMPERATURE &&
483473c88f9SBruce Richardson 	    prop->prop_id != FME_THERMAL_PROP_REVISION)
484473c88f9SBruce Richardson 		return -ENOENT;
485473c88f9SBruce Richardson 
486473c88f9SBruce Richardson 	switch (prop->prop_id) {
487473c88f9SBruce Richardson 	case FME_THERMAL_PROP_THRESHOLD1:
488473c88f9SBruce Richardson 		return fme_thermal_get_threshold1(fme, &prop->data);
489473c88f9SBruce Richardson 	case FME_THERMAL_PROP_THRESHOLD2:
490473c88f9SBruce Richardson 		return fme_thermal_get_threshold2(fme, &prop->data);
491473c88f9SBruce Richardson 	case FME_THERMAL_PROP_THRESHOLD_TRIP:
492473c88f9SBruce Richardson 		return fme_thermal_get_threshold_trip(fme, &prop->data);
493473c88f9SBruce Richardson 	case FME_THERMAL_PROP_THRESHOLD1_REACHED:
494473c88f9SBruce Richardson 		return fme_thermal_get_threshold1_reached(fme, &prop->data);
495473c88f9SBruce Richardson 	case FME_THERMAL_PROP_THRESHOLD2_REACHED:
496473c88f9SBruce Richardson 		return fme_thermal_get_threshold2_reached(fme, &prop->data);
497473c88f9SBruce Richardson 	case FME_THERMAL_PROP_THRESHOLD1_POLICY:
498473c88f9SBruce Richardson 		return fme_thermal_get_threshold1_policy(fme, &prop->data);
499473c88f9SBruce Richardson 	case FME_THERMAL_PROP_TEMPERATURE:
500473c88f9SBruce Richardson 		return fme_thermal_get_temperature(fme, &prop->data);
501473c88f9SBruce Richardson 	case FME_THERMAL_PROP_REVISION:
502473c88f9SBruce Richardson 		return fme_thermal_get_revision(fme, &prop->data);
503473c88f9SBruce Richardson 	}
504473c88f9SBruce Richardson 
505473c88f9SBruce Richardson 	return -ENOENT;
506473c88f9SBruce Richardson }
507473c88f9SBruce Richardson 
508473c88f9SBruce Richardson struct ifpga_feature_ops fme_thermal_mgmt_ops = {
509473c88f9SBruce Richardson 	.init = fme_thermal_mgmt_init,
510473c88f9SBruce Richardson 	.uinit = fme_thermal_mgmt_uinit,
511473c88f9SBruce Richardson 	.get_prop = fme_thermal_get_prop,
512473c88f9SBruce Richardson 	.set_prop = fme_thermal_set_prop,
513473c88f9SBruce Richardson };
514473c88f9SBruce Richardson 
fme_pwr_get_consumed(struct ifpga_fme_hw * fme,u64 * consumed)515473c88f9SBruce Richardson static int fme_pwr_get_consumed(struct ifpga_fme_hw *fme, u64 *consumed)
516473c88f9SBruce Richardson {
517473c88f9SBruce Richardson 	struct feature_fme_power *fme_power
518473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
519473c88f9SBruce Richardson 				FME_FEATURE_ID_POWER_MGMT);
520473c88f9SBruce Richardson 	struct feature_fme_pm_status pm_status;
521473c88f9SBruce Richardson 
522473c88f9SBruce Richardson 	pm_status.csr = readq(&fme_power->status);
523473c88f9SBruce Richardson 
524473c88f9SBruce Richardson 	*consumed = pm_status.pwr_consumed;
525473c88f9SBruce Richardson 
526473c88f9SBruce Richardson 	return 0;
527473c88f9SBruce Richardson }
528473c88f9SBruce Richardson 
fme_pwr_get_threshold1(struct ifpga_fme_hw * fme,u64 * threshold)529473c88f9SBruce Richardson static int fme_pwr_get_threshold1(struct ifpga_fme_hw *fme, u64 *threshold)
530473c88f9SBruce Richardson {
531473c88f9SBruce Richardson 	struct feature_fme_power *fme_power
532473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
533473c88f9SBruce Richardson 				FME_FEATURE_ID_POWER_MGMT);
534473c88f9SBruce Richardson 	struct feature_fme_pm_ap_threshold pm_ap_threshold;
535473c88f9SBruce Richardson 
536473c88f9SBruce Richardson 	pm_ap_threshold.csr = readq(&fme_power->threshold);
537473c88f9SBruce Richardson 
538473c88f9SBruce Richardson 	*threshold = pm_ap_threshold.threshold1;
539473c88f9SBruce Richardson 
540473c88f9SBruce Richardson 	return 0;
541473c88f9SBruce Richardson }
542473c88f9SBruce Richardson 
fme_pwr_set_threshold1(struct ifpga_fme_hw * fme,u64 threshold)543473c88f9SBruce Richardson static int fme_pwr_set_threshold1(struct ifpga_fme_hw *fme, u64 threshold)
544473c88f9SBruce Richardson {
545473c88f9SBruce Richardson 	struct feature_fme_power *fme_power
546473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
547473c88f9SBruce Richardson 				FME_FEATURE_ID_POWER_MGMT);
548473c88f9SBruce Richardson 	struct feature_fme_pm_ap_threshold pm_ap_threshold;
549473c88f9SBruce Richardson 
550473c88f9SBruce Richardson 	spinlock_lock(&fme->lock);
551473c88f9SBruce Richardson 	pm_ap_threshold.csr = readq(&fme_power->threshold);
552473c88f9SBruce Richardson 
553473c88f9SBruce Richardson 	if (threshold <= PWR_THRESHOLD_MAX) {
554473c88f9SBruce Richardson 		pm_ap_threshold.threshold1 = threshold;
555473c88f9SBruce Richardson 	} else {
556473c88f9SBruce Richardson 		spinlock_unlock(&fme->lock);
557473c88f9SBruce Richardson 		return -EINVAL;
558473c88f9SBruce Richardson 	}
559473c88f9SBruce Richardson 
560473c88f9SBruce Richardson 	writeq(pm_ap_threshold.csr, &fme_power->threshold);
561473c88f9SBruce Richardson 	spinlock_unlock(&fme->lock);
562473c88f9SBruce Richardson 
563473c88f9SBruce Richardson 	return 0;
564473c88f9SBruce Richardson }
565473c88f9SBruce Richardson 
fme_pwr_get_threshold2(struct ifpga_fme_hw * fme,u64 * threshold)566473c88f9SBruce Richardson static int fme_pwr_get_threshold2(struct ifpga_fme_hw *fme, u64 *threshold)
567473c88f9SBruce Richardson {
568473c88f9SBruce Richardson 	struct feature_fme_power *fme_power
569473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
570473c88f9SBruce Richardson 				FME_FEATURE_ID_POWER_MGMT);
571473c88f9SBruce Richardson 	struct feature_fme_pm_ap_threshold pm_ap_threshold;
572473c88f9SBruce Richardson 
573473c88f9SBruce Richardson 	pm_ap_threshold.csr = readq(&fme_power->threshold);
574473c88f9SBruce Richardson 
575473c88f9SBruce Richardson 	*threshold = pm_ap_threshold.threshold2;
576473c88f9SBruce Richardson 
577473c88f9SBruce Richardson 	return 0;
578473c88f9SBruce Richardson }
579473c88f9SBruce Richardson 
fme_pwr_set_threshold2(struct ifpga_fme_hw * fme,u64 threshold)580473c88f9SBruce Richardson static int fme_pwr_set_threshold2(struct ifpga_fme_hw *fme, u64 threshold)
581473c88f9SBruce Richardson {
582473c88f9SBruce Richardson 	struct feature_fme_power *fme_power
583473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
584473c88f9SBruce Richardson 				FME_FEATURE_ID_POWER_MGMT);
585473c88f9SBruce Richardson 	struct feature_fme_pm_ap_threshold pm_ap_threshold;
586473c88f9SBruce Richardson 
587473c88f9SBruce Richardson 	spinlock_lock(&fme->lock);
588473c88f9SBruce Richardson 	pm_ap_threshold.csr = readq(&fme_power->threshold);
589473c88f9SBruce Richardson 
590473c88f9SBruce Richardson 	if (threshold <= PWR_THRESHOLD_MAX) {
591473c88f9SBruce Richardson 		pm_ap_threshold.threshold2 = threshold;
592473c88f9SBruce Richardson 	} else {
593473c88f9SBruce Richardson 		spinlock_unlock(&fme->lock);
594473c88f9SBruce Richardson 		return -EINVAL;
595473c88f9SBruce Richardson 	}
596473c88f9SBruce Richardson 
597473c88f9SBruce Richardson 	writeq(pm_ap_threshold.csr, &fme_power->threshold);
598473c88f9SBruce Richardson 	spinlock_unlock(&fme->lock);
599473c88f9SBruce Richardson 
600473c88f9SBruce Richardson 	return 0;
601473c88f9SBruce Richardson }
602473c88f9SBruce Richardson 
fme_pwr_get_threshold1_status(struct ifpga_fme_hw * fme,u64 * threshold_status)603473c88f9SBruce Richardson static int fme_pwr_get_threshold1_status(struct ifpga_fme_hw *fme,
604473c88f9SBruce Richardson 					 u64 *threshold_status)
605473c88f9SBruce Richardson {
606473c88f9SBruce Richardson 	struct feature_fme_power *fme_power
607473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
608473c88f9SBruce Richardson 				FME_FEATURE_ID_POWER_MGMT);
609473c88f9SBruce Richardson 	struct feature_fme_pm_ap_threshold pm_ap_threshold;
610473c88f9SBruce Richardson 
611473c88f9SBruce Richardson 	pm_ap_threshold.csr = readq(&fme_power->threshold);
612473c88f9SBruce Richardson 
613473c88f9SBruce Richardson 	*threshold_status = pm_ap_threshold.threshold1_status;
614473c88f9SBruce Richardson 
615473c88f9SBruce Richardson 	return 0;
616473c88f9SBruce Richardson }
617473c88f9SBruce Richardson 
fme_pwr_get_threshold2_status(struct ifpga_fme_hw * fme,u64 * threshold_status)618473c88f9SBruce Richardson static int fme_pwr_get_threshold2_status(struct ifpga_fme_hw *fme,
619473c88f9SBruce Richardson 					 u64 *threshold_status)
620473c88f9SBruce Richardson {
621473c88f9SBruce Richardson 	struct feature_fme_power *fme_power
622473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
623473c88f9SBruce Richardson 				FME_FEATURE_ID_POWER_MGMT);
624473c88f9SBruce Richardson 	struct feature_fme_pm_ap_threshold pm_ap_threshold;
625473c88f9SBruce Richardson 
626473c88f9SBruce Richardson 	pm_ap_threshold.csr = readq(&fme_power->threshold);
627473c88f9SBruce Richardson 
628473c88f9SBruce Richardson 	*threshold_status = pm_ap_threshold.threshold2_status;
629473c88f9SBruce Richardson 
630473c88f9SBruce Richardson 	return 0;
631473c88f9SBruce Richardson }
632473c88f9SBruce Richardson 
fme_pwr_get_rtl(struct ifpga_fme_hw * fme,u64 * rtl)633473c88f9SBruce Richardson static int fme_pwr_get_rtl(struct ifpga_fme_hw *fme, u64 *rtl)
634473c88f9SBruce Richardson {
635473c88f9SBruce Richardson 	struct feature_fme_power *fme_power
636473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
637473c88f9SBruce Richardson 				FME_FEATURE_ID_POWER_MGMT);
638473c88f9SBruce Richardson 	struct feature_fme_pm_status pm_status;
639473c88f9SBruce Richardson 
640473c88f9SBruce Richardson 	pm_status.csr = readq(&fme_power->status);
641473c88f9SBruce Richardson 
642473c88f9SBruce Richardson 	*rtl = pm_status.fpga_latency_report;
643473c88f9SBruce Richardson 
644473c88f9SBruce Richardson 	return 0;
645473c88f9SBruce Richardson }
646473c88f9SBruce Richardson 
fme_pwr_get_xeon_limit(struct ifpga_fme_hw * fme,u64 * limit)647473c88f9SBruce Richardson static int fme_pwr_get_xeon_limit(struct ifpga_fme_hw *fme, u64 *limit)
648473c88f9SBruce Richardson {
649473c88f9SBruce Richardson 	struct feature_fme_power *fme_power
650473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
651473c88f9SBruce Richardson 				FME_FEATURE_ID_POWER_MGMT);
652473c88f9SBruce Richardson 	struct feature_fme_pm_xeon_limit xeon_limit;
653473c88f9SBruce Richardson 
654473c88f9SBruce Richardson 	xeon_limit.csr = readq(&fme_power->xeon_limit);
655473c88f9SBruce Richardson 
656473c88f9SBruce Richardson 	if (!xeon_limit.enable)
657473c88f9SBruce Richardson 		xeon_limit.pwr_limit = 0;
658473c88f9SBruce Richardson 
659473c88f9SBruce Richardson 	*limit = xeon_limit.pwr_limit;
660473c88f9SBruce Richardson 
661473c88f9SBruce Richardson 	return 0;
662473c88f9SBruce Richardson }
663473c88f9SBruce Richardson 
fme_pwr_get_fpga_limit(struct ifpga_fme_hw * fme,u64 * limit)664473c88f9SBruce Richardson static int fme_pwr_get_fpga_limit(struct ifpga_fme_hw *fme, u64 *limit)
665473c88f9SBruce Richardson {
666473c88f9SBruce Richardson 	struct feature_fme_power *fme_power
667473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
668473c88f9SBruce Richardson 				FME_FEATURE_ID_POWER_MGMT);
669473c88f9SBruce Richardson 	struct feature_fme_pm_fpga_limit fpga_limit;
670473c88f9SBruce Richardson 
671473c88f9SBruce Richardson 	fpga_limit.csr = readq(&fme_power->fpga_limit);
672473c88f9SBruce Richardson 
673473c88f9SBruce Richardson 	if (!fpga_limit.enable)
674473c88f9SBruce Richardson 		fpga_limit.pwr_limit = 0;
675473c88f9SBruce Richardson 
676473c88f9SBruce Richardson 	*limit = fpga_limit.pwr_limit;
677473c88f9SBruce Richardson 
678473c88f9SBruce Richardson 	return 0;
679473c88f9SBruce Richardson }
680473c88f9SBruce Richardson 
fme_pwr_get_revision(struct ifpga_fme_hw * fme,u64 * revision)681473c88f9SBruce Richardson static int fme_pwr_get_revision(struct ifpga_fme_hw *fme, u64 *revision)
682473c88f9SBruce Richardson {
683473c88f9SBruce Richardson 	struct feature_fme_power *fme_power
684473c88f9SBruce Richardson 		= get_fme_feature_ioaddr_by_index(fme,
685473c88f9SBruce Richardson 						  FME_FEATURE_ID_POWER_MGMT);
686473c88f9SBruce Richardson 	struct feature_header header;
687473c88f9SBruce Richardson 
688473c88f9SBruce Richardson 	header.csr = readq(&fme_power->header);
689473c88f9SBruce Richardson 	*revision = header.revision;
690473c88f9SBruce Richardson 
691473c88f9SBruce Richardson 	return 0;
692473c88f9SBruce Richardson }
693473c88f9SBruce Richardson 
fme_power_mgmt_init(struct ifpga_feature * feature)694473c88f9SBruce Richardson static int fme_power_mgmt_init(struct ifpga_feature *feature)
695473c88f9SBruce Richardson {
696473c88f9SBruce Richardson 	UNUSED(feature);
697473c88f9SBruce Richardson 
698473c88f9SBruce Richardson 	dev_info(NULL, "FME power mgmt Init.\n");
699473c88f9SBruce Richardson 
700473c88f9SBruce Richardson 	return 0;
701473c88f9SBruce Richardson }
702473c88f9SBruce Richardson 
fme_power_mgmt_uinit(struct ifpga_feature * feature)703473c88f9SBruce Richardson static void fme_power_mgmt_uinit(struct ifpga_feature *feature)
704473c88f9SBruce Richardson {
705473c88f9SBruce Richardson 	UNUSED(feature);
706473c88f9SBruce Richardson 
707473c88f9SBruce Richardson 	dev_info(NULL, "FME power mgmt UInit.\n");
708473c88f9SBruce Richardson }
709473c88f9SBruce Richardson 
fme_power_mgmt_get_prop(struct ifpga_feature * feature,struct feature_prop * prop)710473c88f9SBruce Richardson static int fme_power_mgmt_get_prop(struct ifpga_feature *feature,
711473c88f9SBruce Richardson 				   struct feature_prop *prop)
712473c88f9SBruce Richardson {
713473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = feature->parent;
714473c88f9SBruce Richardson 
715473c88f9SBruce Richardson 	switch (prop->prop_id) {
716473c88f9SBruce Richardson 	case FME_PWR_PROP_CONSUMED:
717473c88f9SBruce Richardson 		return fme_pwr_get_consumed(fme, &prop->data);
718473c88f9SBruce Richardson 	case FME_PWR_PROP_THRESHOLD1:
719473c88f9SBruce Richardson 		return fme_pwr_get_threshold1(fme, &prop->data);
720473c88f9SBruce Richardson 	case FME_PWR_PROP_THRESHOLD2:
721473c88f9SBruce Richardson 		return fme_pwr_get_threshold2(fme, &prop->data);
722473c88f9SBruce Richardson 	case FME_PWR_PROP_THRESHOLD1_STATUS:
723473c88f9SBruce Richardson 		return fme_pwr_get_threshold1_status(fme, &prop->data);
724473c88f9SBruce Richardson 	case FME_PWR_PROP_THRESHOLD2_STATUS:
725473c88f9SBruce Richardson 		return fme_pwr_get_threshold2_status(fme, &prop->data);
726473c88f9SBruce Richardson 	case FME_PWR_PROP_RTL:
727473c88f9SBruce Richardson 		return fme_pwr_get_rtl(fme, &prop->data);
728473c88f9SBruce Richardson 	case FME_PWR_PROP_XEON_LIMIT:
729473c88f9SBruce Richardson 		return fme_pwr_get_xeon_limit(fme, &prop->data);
730473c88f9SBruce Richardson 	case FME_PWR_PROP_FPGA_LIMIT:
731473c88f9SBruce Richardson 		return fme_pwr_get_fpga_limit(fme, &prop->data);
732473c88f9SBruce Richardson 	case FME_PWR_PROP_REVISION:
733473c88f9SBruce Richardson 		return fme_pwr_get_revision(fme, &prop->data);
734473c88f9SBruce Richardson 	}
735473c88f9SBruce Richardson 
736473c88f9SBruce Richardson 	return -ENOENT;
737473c88f9SBruce Richardson }
738473c88f9SBruce Richardson 
fme_power_mgmt_set_prop(struct ifpga_feature * feature,struct feature_prop * prop)739473c88f9SBruce Richardson static int fme_power_mgmt_set_prop(struct ifpga_feature *feature,
740473c88f9SBruce Richardson 				   struct feature_prop *prop)
741473c88f9SBruce Richardson {
742473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = feature->parent;
743473c88f9SBruce Richardson 
744473c88f9SBruce Richardson 	switch (prop->prop_id) {
745473c88f9SBruce Richardson 	case FME_PWR_PROP_THRESHOLD1:
746473c88f9SBruce Richardson 		return fme_pwr_set_threshold1(fme, prop->data);
747473c88f9SBruce Richardson 	case FME_PWR_PROP_THRESHOLD2:
748473c88f9SBruce Richardson 		return fme_pwr_set_threshold2(fme, prop->data);
749473c88f9SBruce Richardson 	}
750473c88f9SBruce Richardson 
751473c88f9SBruce Richardson 	return -ENOENT;
752473c88f9SBruce Richardson }
753473c88f9SBruce Richardson 
754473c88f9SBruce Richardson struct ifpga_feature_ops fme_power_mgmt_ops = {
755473c88f9SBruce Richardson 	.init = fme_power_mgmt_init,
756473c88f9SBruce Richardson 	.uinit = fme_power_mgmt_uinit,
757473c88f9SBruce Richardson 	.get_prop = fme_power_mgmt_get_prop,
758473c88f9SBruce Richardson 	.set_prop = fme_power_mgmt_set_prop,
759473c88f9SBruce Richardson };
760473c88f9SBruce Richardson 
fme_hssi_eth_init(struct ifpga_feature * feature)761473c88f9SBruce Richardson static int fme_hssi_eth_init(struct ifpga_feature *feature)
762473c88f9SBruce Richardson {
763473c88f9SBruce Richardson 	UNUSED(feature);
764473c88f9SBruce Richardson 	return 0;
765473c88f9SBruce Richardson }
766473c88f9SBruce Richardson 
fme_hssi_eth_uinit(struct ifpga_feature * feature)767473c88f9SBruce Richardson static void fme_hssi_eth_uinit(struct ifpga_feature *feature)
768473c88f9SBruce Richardson {
769473c88f9SBruce Richardson 	UNUSED(feature);
770473c88f9SBruce Richardson }
771473c88f9SBruce Richardson 
772473c88f9SBruce Richardson struct ifpga_feature_ops fme_hssi_eth_ops = {
773473c88f9SBruce Richardson 	.init = fme_hssi_eth_init,
774473c88f9SBruce Richardson 	.uinit = fme_hssi_eth_uinit,
775473c88f9SBruce Richardson };
776473c88f9SBruce Richardson 
fme_emif_init(struct ifpga_feature * feature)777473c88f9SBruce Richardson static int fme_emif_init(struct ifpga_feature *feature)
778473c88f9SBruce Richardson {
779473c88f9SBruce Richardson 	UNUSED(feature);
780473c88f9SBruce Richardson 	return 0;
781473c88f9SBruce Richardson }
782473c88f9SBruce Richardson 
fme_emif_uinit(struct ifpga_feature * feature)783473c88f9SBruce Richardson static void fme_emif_uinit(struct ifpga_feature *feature)
784473c88f9SBruce Richardson {
785473c88f9SBruce Richardson 	UNUSED(feature);
786473c88f9SBruce Richardson }
787473c88f9SBruce Richardson 
788473c88f9SBruce Richardson struct ifpga_feature_ops fme_emif_ops = {
789473c88f9SBruce Richardson 	.init = fme_emif_init,
790473c88f9SBruce Richardson 	.uinit = fme_emif_uinit,
791473c88f9SBruce Richardson };
792473c88f9SBruce Richardson 
board_type_to_string(u32 board,u32 type)7937c4fe2adSWei Huang static const char *board_type_to_string(u32 board, u32 type)
794473c88f9SBruce Richardson {
7957c4fe2adSWei Huang 	if (board == VISTA_CREEK) {
796473c88f9SBruce Richardson 		switch (type) {
797473c88f9SBruce Richardson 		case VC_8_10G:
7987c4fe2adSWei Huang 			return "8x10G";
799473c88f9SBruce Richardson 		case VC_4_25G:
8007c4fe2adSWei Huang 			return "4x25G";
801473c88f9SBruce Richardson 		case VC_2_1_25:
8027c4fe2adSWei Huang 			return "2x1x25G";
803473c88f9SBruce Richardson 		case VC_4_25G_2_25G:
8047c4fe2adSWei Huang 			return "4x25G+2x25G";
805473c88f9SBruce Richardson 		case VC_2_2_25G:
8067c4fe2adSWei Huang 			return "2x2x25G";
8077c4fe2adSWei Huang 		break;
8087c4fe2adSWei Huang 		}
8097c4fe2adSWei Huang 	} else {
8107c4fe2adSWei Huang 		switch (type) {
8117c4fe2adSWei Huang 		case FIMA_10G_ADP:
8127c4fe2adSWei Huang 			return "2x4x10G";
8137c4fe2adSWei Huang 		case FIMA_25G_ADP:
8147c4fe2adSWei Huang 			return "2x2x25G";
8157c4fe2adSWei Huang 		case FIMA_100G_ADP:
8167c4fe2adSWei Huang 			return "2x100G";
8177c4fe2adSWei Huang 		break;
8187c4fe2adSWei Huang 		}
819473c88f9SBruce Richardson 	}
820473c88f9SBruce Richardson 
821473c88f9SBruce Richardson 	return "unknown";
822473c88f9SBruce Richardson }
823473c88f9SBruce Richardson 
board_major_to_string(u32 major)824c127953fSTianfei Zhang static const char *board_major_to_string(u32 major)
825c127953fSTianfei Zhang {
826c127953fSTianfei Zhang 	switch (major) {
827c127953fSTianfei Zhang 	case VISTA_CREEK:
828c127953fSTianfei Zhang 		return "VISTA_CREEK";
829c127953fSTianfei Zhang 	case RUSH_CREEK:
830c127953fSTianfei Zhang 		return "RUSH_CREEK";
831c127953fSTianfei Zhang 	case DARBY_CREEK:
832c127953fSTianfei Zhang 		return "DARBY_CREEK";
8337c4fe2adSWei Huang 	case LIGHTNING_CREEK:
8347c4fe2adSWei Huang 		return "LIGHTNING_CREEK";
8357c4fe2adSWei Huang 	case ARROW_CREEK:
8367c4fe2adSWei Huang 		return "ARROW_CREEK";
8377c4fe2adSWei Huang 	default:
8387c4fe2adSWei Huang 		break;
839c127953fSTianfei Zhang 	}
840c127953fSTianfei Zhang 
841c127953fSTianfei Zhang 	return "unknown";
842c127953fSTianfei Zhang }
843c127953fSTianfei Zhang 
board_type_to_info(u32 type,struct opae_board_info * info)844473c88f9SBruce Richardson static int board_type_to_info(u32 type,
845c127953fSTianfei Zhang 		struct opae_board_info *info)
846473c88f9SBruce Richardson {
847473c88f9SBruce Richardson 	switch (type) {
848473c88f9SBruce Richardson 	case VC_8_10G:
849473c88f9SBruce Richardson 		info->nums_of_retimer = 2;
850473c88f9SBruce Richardson 		info->ports_per_retimer = 4;
851473c88f9SBruce Richardson 		info->nums_of_fvl = 2;
852473c88f9SBruce Richardson 		info->ports_per_fvl = 4;
853473c88f9SBruce Richardson 		break;
854473c88f9SBruce Richardson 	case VC_4_25G:
855473c88f9SBruce Richardson 		info->nums_of_retimer = 1;
856473c88f9SBruce Richardson 		info->ports_per_retimer = 4;
857473c88f9SBruce Richardson 		info->nums_of_fvl = 2;
858473c88f9SBruce Richardson 		info->ports_per_fvl = 2;
859473c88f9SBruce Richardson 		break;
860473c88f9SBruce Richardson 	case VC_2_1_25:
861473c88f9SBruce Richardson 		info->nums_of_retimer = 2;
862473c88f9SBruce Richardson 		info->ports_per_retimer = 1;
863473c88f9SBruce Richardson 		info->nums_of_fvl = 1;
864473c88f9SBruce Richardson 		info->ports_per_fvl = 2;
865473c88f9SBruce Richardson 		break;
866473c88f9SBruce Richardson 	case VC_2_2_25G:
867473c88f9SBruce Richardson 		info->nums_of_retimer = 2;
868473c88f9SBruce Richardson 		info->ports_per_retimer = 2;
869473c88f9SBruce Richardson 		info->nums_of_fvl = 2;
870473c88f9SBruce Richardson 		info->ports_per_fvl = 2;
871473c88f9SBruce Richardson 		break;
872473c88f9SBruce Richardson 	default:
873473c88f9SBruce Richardson 		return -EINVAL;
874473c88f9SBruce Richardson 	}
875473c88f9SBruce Richardson 
876473c88f9SBruce Richardson 	return 0;
877473c88f9SBruce Richardson }
878473c88f9SBruce Richardson 
fme_get_board_interface(struct ifpga_fme_hw * fme)879473c88f9SBruce Richardson static int fme_get_board_interface(struct ifpga_fme_hw *fme)
880473c88f9SBruce Richardson {
8817c4fe2adSWei Huang 	struct feature_fme_bitstream_id id;
8824a19f891STianfei Zhang 	struct ifpga_hw *hw;
88371da60b8STianfei Zhang 	u32 val;
8847c4fe2adSWei Huang 	const char *type = NULL;
8857c4fe2adSWei Huang 	int ret;
886473c88f9SBruce Richardson 
8874a19f891STianfei Zhang 	hw = fme->parent;
8884a19f891STianfei Zhang 	if (!hw)
8894a19f891STianfei Zhang 		return -ENODEV;
8904a19f891STianfei Zhang 
8917c4fe2adSWei Huang 	if (fme_hdr_get_bitstream_id(fme, &id.csr))
892473c88f9SBruce Richardson 		return -EINVAL;
893473c88f9SBruce Richardson 
8947c4fe2adSWei Huang 	if (id.v1.major == ARROW_CREEK) {
8957c4fe2adSWei Huang 		fme->board_info.major = id.v2.bs_vermajor;
8967c4fe2adSWei Huang 		fme->board_info.minor = id.v2.bs_verminor;
8977c4fe2adSWei Huang 		fme->board_info.n6000_fim_type = id.v2.fim_type;
8987c4fe2adSWei Huang 		fme->board_info.n6000_hssi_id = id.v2.hssi_id;
8997c4fe2adSWei Huang 		type = board_type_to_string(fme->board_info.major,
9007c4fe2adSWei Huang 				fme->board_info.n6000_fim_type);
9017c4fe2adSWei Huang 	} else {
9027c4fe2adSWei Huang 		fme->board_info.major = id.v1.major;
9037c4fe2adSWei Huang 		fme->board_info.minor = id.v1.minor;
9047c4fe2adSWei Huang 		fme->board_info.type = id.v1.interface;
9057c4fe2adSWei Huang 		fme->board_info.fvl_bypass = id.v1.fvl_bypass;
9067c4fe2adSWei Huang 		fme->board_info.mac_lightweight = id.v1.mac_lightweight;
9077c4fe2adSWei Huang 		fme->board_info.lightweight = id.v1.lightweiht;
9087c4fe2adSWei Huang 		fme->board_info.disaggregate = id.v1.disagregate;
9097c4fe2adSWei Huang 		fme->board_info.seu = id.v1.seu;
9107c4fe2adSWei Huang 		fme->board_info.ptp = id.v1.ptp;
9117c4fe2adSWei Huang 		type = board_type_to_string(fme->board_info.major,
9127c4fe2adSWei Huang 				fme->board_info.type);
9137c4fe2adSWei Huang 	}
914473c88f9SBruce Richardson 
9154a19f891STianfei Zhang 	dev_info(fme, "found: PCI dev: %02x:%02x:%x board: %s type: %s\n",
9164a19f891STianfei Zhang 			hw->pci_data->bus,
9174a19f891STianfei Zhang 			hw->pci_data->devid,
9184a19f891STianfei Zhang 			hw->pci_data->function,
919c127953fSTianfei Zhang 			board_major_to_string(fme->board_info.major),
9207c4fe2adSWei Huang 			type);
921c127953fSTianfei Zhang 
9227c4fe2adSWei Huang 	ret = max10_get_fpga_load_info(fme->max10_dev, &val);
9237c4fe2adSWei Huang 	if (ret)
9247c4fe2adSWei Huang 		return ret;
9257c4fe2adSWei Huang 	fme->board_info.boot_page = val;
9267c4fe2adSWei Huang 
9277c4fe2adSWei Huang 	if (fme->board_info.major == VISTA_CREEK) {
9287c4fe2adSWei Huang 		dev_info(dev, "FPGA loaded from %s Image\n",
9297c4fe2adSWei Huang 			val ? "User" : "Factory");
930c127953fSTianfei Zhang 		dev_info(fme, "support feature:\n"
931c127953fSTianfei Zhang 			"fvl_bypass:%s\n"
932c127953fSTianfei Zhang 			"mac_lightweight:%s\n"
933c127953fSTianfei Zhang 			"lightweight:%s\n"
934c127953fSTianfei Zhang 			"disaggregate:%s\n"
935c127953fSTianfei Zhang 			"seu:%s\n"
936c127953fSTianfei Zhang 			"ptp1588:%s\n",
937c127953fSTianfei Zhang 			check_support(fme->board_info.fvl_bypass),
938c127953fSTianfei Zhang 			check_support(fme->board_info.mac_lightweight),
939c127953fSTianfei Zhang 			check_support(fme->board_info.lightweight),
940c127953fSTianfei Zhang 			check_support(fme->board_info.disaggregate),
941c127953fSTianfei Zhang 			check_support(fme->board_info.seu),
942c127953fSTianfei Zhang 			check_support(fme->board_info.ptp));
943c127953fSTianfei Zhang 
944473c88f9SBruce Richardson 		if (board_type_to_info(fme->board_info.type, &fme->board_info))
945473c88f9SBruce Richardson 			return -EINVAL;
946473c88f9SBruce Richardson 
9477c4fe2adSWei Huang 		dev_info(fme, "get board info: nums_retimers %d "
9487c4fe2adSWei Huang 			"ports_per_retimer %d nums_fvl %d "
9497c4fe2adSWei Huang 			"ports_per_fvl %d\n",
950473c88f9SBruce Richardson 			fme->board_info.nums_of_retimer,
951473c88f9SBruce Richardson 			fme->board_info.ports_per_retimer,
952473c88f9SBruce Richardson 			fme->board_info.nums_of_fvl,
953473c88f9SBruce Richardson 			fme->board_info.ports_per_fvl);
9547c4fe2adSWei Huang 	} else {
9557c4fe2adSWei Huang 		dev_info(dev, "FPGA loaded from %s Image\n",
9567c4fe2adSWei Huang 			val ? (val == 1 ? "User1" : "User2") : "Factory");
9577c4fe2adSWei Huang 	}
958473c88f9SBruce Richardson 
9597c4fe2adSWei Huang 	ret = max10_get_bmc_version(fme->max10_dev, &val);
9607c4fe2adSWei Huang 	if (ret)
9617c4fe2adSWei Huang 		return ret;
962cf38bcd7SWei Huang 	fme->board_info.max10_version = val;
96371da60b8STianfei Zhang 
9647c4fe2adSWei Huang 	ret = max10_get_bmcfw_version(fme->max10_dev, &val);
9657c4fe2adSWei Huang 	if (ret)
9667c4fe2adSWei Huang 		return ret;
967cf38bcd7SWei Huang 	fme->board_info.nios_fw_version = val;
96871da60b8STianfei Zhang 
96971da60b8STianfei Zhang 	dev_info(fme, "max10 version 0x%x, nios fw version 0x%x\n",
97071da60b8STianfei Zhang 		fme->board_info.max10_version,
97171da60b8STianfei Zhang 		fme->board_info.nios_fw_version);
97271da60b8STianfei Zhang 
973473c88f9SBruce Richardson 	return 0;
974473c88f9SBruce Richardson }
975473c88f9SBruce Richardson 
spi_self_checking(struct intel_max10_device * dev)9764a19f891STianfei Zhang static int spi_self_checking(struct intel_max10_device *dev)
977473c88f9SBruce Richardson {
978473c88f9SBruce Richardson 	u32 val;
979473c88f9SBruce Richardson 	int ret;
980473c88f9SBruce Richardson 
9814a19f891STianfei Zhang 	ret = max10_sys_read(dev, MAX10_TEST_REG, &val);
982473c88f9SBruce Richardson 	if (ret)
983473c88f9SBruce Richardson 		return -EIO;
984473c88f9SBruce Richardson 
98571da60b8STianfei Zhang 	dev_info(NULL, "Read MAX10 test register 0x%x\n", val);
986473c88f9SBruce Richardson 
987473c88f9SBruce Richardson 	return 0;
988473c88f9SBruce Richardson }
989473c88f9SBruce Richardson 
init_spi_share_data(struct ifpga_fme_hw * fme,struct altera_spi_device * spi)990e41856b5SWei Huang static void init_spi_share_data(struct ifpga_fme_hw *fme,
991e41856b5SWei Huang 				struct altera_spi_device *spi)
992e41856b5SWei Huang {
993e41856b5SWei Huang 	struct ifpga_hw *hw = (struct ifpga_hw *)fme->parent;
994e41856b5SWei Huang 	opae_share_data *sd = NULL;
995e41856b5SWei Huang 
996e41856b5SWei Huang 	if (hw && hw->adapter && hw->adapter->shm.ptr) {
997e41856b5SWei Huang 		dev_info(NULL, "transfer share data to spi\n");
998e41856b5SWei Huang 		sd = (opae_share_data *)hw->adapter->shm.ptr;
999e41856b5SWei Huang 		spi->mutex = &sd->spi_mutex;
1000e41856b5SWei Huang 		spi->dtb_sz_ptr = &sd->dtb_size;
1001e41856b5SWei Huang 		spi->dtb = sd->dtb;
1002e41856b5SWei Huang 	} else {
1003e41856b5SWei Huang 		spi->mutex = NULL;
1004e41856b5SWei Huang 		spi->dtb_sz_ptr = NULL;
1005e41856b5SWei Huang 		spi->dtb = NULL;
1006e41856b5SWei Huang 	}
1007e41856b5SWei Huang }
1008e41856b5SWei Huang 
fme_spi_init(struct ifpga_feature * feature)1009473c88f9SBruce Richardson static int fme_spi_init(struct ifpga_feature *feature)
1010473c88f9SBruce Richardson {
1011473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
1012473c88f9SBruce Richardson 	struct altera_spi_device *spi_master;
1013473c88f9SBruce Richardson 	struct intel_max10_device *max10;
1014473c88f9SBruce Richardson 	int ret = 0;
1015473c88f9SBruce Richardson 
1016473c88f9SBruce Richardson 	dev_info(fme, "FME SPI Master (Max10) Init.\n");
1017473c88f9SBruce Richardson 	dev_debug(fme, "FME SPI base addr %p.\n",
1018473c88f9SBruce Richardson 			feature->addr);
1019473c88f9SBruce Richardson 	dev_debug(fme, "spi param=0x%llx\n",
1020473c88f9SBruce Richardson 			(unsigned long long)opae_readq(feature->addr + 0x8));
1021473c88f9SBruce Richardson 
1022473c88f9SBruce Richardson 	spi_master = altera_spi_alloc(feature->addr, TYPE_SPI);
1023473c88f9SBruce Richardson 	if (!spi_master)
1024473c88f9SBruce Richardson 		return -ENODEV;
1025e41856b5SWei Huang 	init_spi_share_data(fme, spi_master);
1026473c88f9SBruce Richardson 
1027473c88f9SBruce Richardson 	altera_spi_init(spi_master);
1028473c88f9SBruce Richardson 
1029ca6eb0f7SWei Huang 	max10 = opae_zmalloc(sizeof(*max10));
1030ca6eb0f7SWei Huang 	if (!max10)
1031ca6eb0f7SWei Huang 		goto release_dev;
1032ca6eb0f7SWei Huang 
1033ca6eb0f7SWei Huang 	max10->spi_master = spi_master;
1034ca6eb0f7SWei Huang 	max10->type = M10_N3000;
1035ca6eb0f7SWei Huang 
1036ca6eb0f7SWei Huang 	max10->spi_tran_dev = spi_transaction_init(spi_master, 0);
1037ca6eb0f7SWei Huang 	if (!max10->spi_tran_dev) {
1038ca6eb0f7SWei Huang 		dev_err(fme, "%s spi tran init fail\n", __func__);
1039ca6eb0f7SWei Huang 		goto free_max10;
1040ca6eb0f7SWei Huang 	}
1041ca6eb0f7SWei Huang 
1042ca6eb0f7SWei Huang 	/* init the max10 device */
1043ca6eb0f7SWei Huang 	ret = intel_max10_device_init(max10);
1044ca6eb0f7SWei Huang 	if (ret) {
1045473c88f9SBruce Richardson 		ret = -ENODEV;
1046473c88f9SBruce Richardson 		dev_err(fme, "max10 init fail\n");
1047ca6eb0f7SWei Huang 		goto release_spi_tran_dev;
1048473c88f9SBruce Richardson 	}
1049473c88f9SBruce Richardson 
1050473c88f9SBruce Richardson 	fme->max10_dev = max10;
1051473c88f9SBruce Richardson 
1052473c88f9SBruce Richardson 	/* SPI self test */
10534a19f891STianfei Zhang 	if (spi_self_checking(max10)) {
1054473c88f9SBruce Richardson 		ret = -EIO;
1055473c88f9SBruce Richardson 		goto max10_fail;
1056473c88f9SBruce Richardson 	}
1057473c88f9SBruce Richardson 
1058473c88f9SBruce Richardson 	return ret;
1059473c88f9SBruce Richardson 
1060473c88f9SBruce Richardson max10_fail:
1061473c88f9SBruce Richardson 	intel_max10_device_remove(fme->max10_dev);
1062ca6eb0f7SWei Huang release_spi_tran_dev:
1063ca6eb0f7SWei Huang 	if (max10->spi_tran_dev)
1064ca6eb0f7SWei Huang 		spi_transaction_remove(max10->spi_tran_dev);
1065ca6eb0f7SWei Huang free_max10:
1066ca6eb0f7SWei Huang 	opae_free(max10);
1067ca6eb0f7SWei Huang release_dev:
1068473c88f9SBruce Richardson 	altera_spi_release(spi_master);
10697c4fe2adSWei Huang 	return -ENODEV;
1070473c88f9SBruce Richardson }
1071473c88f9SBruce Richardson 
fme_spi_uinit(struct ifpga_feature * feature)1072473c88f9SBruce Richardson static void fme_spi_uinit(struct ifpga_feature *feature)
1073473c88f9SBruce Richardson {
1074473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
1075473c88f9SBruce Richardson 
1076ca6eb0f7SWei Huang 	if (fme->max10_dev) {
1077473c88f9SBruce Richardson 		intel_max10_device_remove(fme->max10_dev);
1078ca6eb0f7SWei Huang 		opae_free(fme->max10_dev);
1079ca6eb0f7SWei Huang 	}
1080473c88f9SBruce Richardson }
1081473c88f9SBruce Richardson 
1082473c88f9SBruce Richardson struct ifpga_feature_ops fme_spi_master_ops = {
1083473c88f9SBruce Richardson 	.init = fme_spi_init,
1084473c88f9SBruce Richardson 	.uinit = fme_spi_uinit,
1085473c88f9SBruce Richardson };
1086473c88f9SBruce Richardson 
nios_spi_wait_init_done(struct altera_spi_device * dev)1087473c88f9SBruce Richardson static int nios_spi_wait_init_done(struct altera_spi_device *dev)
1088473c88f9SBruce Richardson {
1089473c88f9SBruce Richardson 	u32 val = 0;
1090cbcf2263STianfei Zhang 	unsigned long timeout = rte_get_timer_cycles() +
1091cbcf2263STianfei Zhang 			msecs_to_timer_cycles(10000);
1092473c88f9SBruce Richardson 	unsigned long ticks;
1093bc44402fSTianfei Zhang 	int major_version;
1094cbcf2263STianfei Zhang 	int fecmode = FEC_MODE_NO;
1095473c88f9SBruce Richardson 
1096bc44402fSTianfei Zhang 	if (spi_reg_read(dev, NIOS_VERSION, &val))
1097bc44402fSTianfei Zhang 		return -EIO;
1098bc44402fSTianfei Zhang 
1099cbcf2263STianfei Zhang 	major_version =
1100cbcf2263STianfei Zhang 		(val & NIOS_VERSION_MAJOR) >> NIOS_VERSION_MAJOR_SHIFT;
1101cbcf2263STianfei Zhang 	dev_info(dev, "A10 NIOS FW version %d\n", major_version);
1102bc44402fSTianfei Zhang 
1103bc44402fSTianfei Zhang 	if (major_version >= 3) {
1104bc44402fSTianfei Zhang 		/* read NIOS_INIT to check if PKVL INIT done or not */
1105bc44402fSTianfei Zhang 		if (spi_reg_read(dev, NIOS_INIT, &val))
1106bc44402fSTianfei Zhang 			return -EIO;
1107bc44402fSTianfei Zhang 
1108cbcf2263STianfei Zhang 		dev_debug(dev, "read NIOS_INIT: 0x%x\n", val);
1109cbcf2263STianfei Zhang 
1110bc44402fSTianfei Zhang 		/* check if PKVLs are initialized already */
1111bc44402fSTianfei Zhang 		if (val & NIOS_INIT_DONE || val & NIOS_INIT_START)
1112bc44402fSTianfei Zhang 			goto nios_init_done;
1113bc44402fSTianfei Zhang 
1114bc44402fSTianfei Zhang 		/* start to config the default FEC mode */
1115cbcf2263STianfei Zhang 		val = fecmode | NIOS_INIT_START;
1116bc44402fSTianfei Zhang 
1117bc44402fSTianfei Zhang 		if (spi_reg_write(dev, NIOS_INIT, val))
1118bc44402fSTianfei Zhang 			return -EIO;
1119bc44402fSTianfei Zhang 	}
1120bc44402fSTianfei Zhang 
1121bc44402fSTianfei Zhang nios_init_done:
1122473c88f9SBruce Richardson 	do {
1123bc44402fSTianfei Zhang 		if (spi_reg_read(dev, NIOS_INIT, &val))
1124473c88f9SBruce Richardson 			return -EIO;
1125cbcf2263STianfei Zhang 		if (val & NIOS_INIT_DONE)
1126473c88f9SBruce Richardson 			break;
1127473c88f9SBruce Richardson 
1128473c88f9SBruce Richardson 		ticks = rte_get_timer_cycles();
1129473c88f9SBruce Richardson 		if (time_after(ticks, timeout))
1130473c88f9SBruce Richardson 			return -ETIMEDOUT;
1131473c88f9SBruce Richardson 		msleep(100);
1132cbcf2263STianfei Zhang 	} while (1);
1133cbcf2263STianfei Zhang 
1134cbcf2263STianfei Zhang 	/* get the fecmode */
1135cbcf2263STianfei Zhang 	if (spi_reg_read(dev, NIOS_INIT, &val))
1136cbcf2263STianfei Zhang 		return -EIO;
1137cbcf2263STianfei Zhang 	dev_debug(dev, "read NIOS_INIT: 0x%x\n", val);
1138cbcf2263STianfei Zhang 	fecmode = (val & REQ_FEC_MODE) >> REQ_FEC_MODE_SHIFT;
1139cbcf2263STianfei Zhang 	dev_info(dev, "fecmode: 0x%x, %s\n", fecmode,
1140cbcf2263STianfei Zhang 			(fecmode == FEC_MODE_KR) ? "kr" :
1141cbcf2263STianfei Zhang 			((fecmode == FEC_MODE_RS) ? "rs" : "no"));
1142473c88f9SBruce Richardson 
1143473c88f9SBruce Richardson 	return 0;
1144473c88f9SBruce Richardson }
1145473c88f9SBruce Richardson 
nios_spi_check_error(struct altera_spi_device * dev)1146473c88f9SBruce Richardson static int nios_spi_check_error(struct altera_spi_device *dev)
1147473c88f9SBruce Richardson {
1148473c88f9SBruce Richardson 	u32 value = 0;
1149473c88f9SBruce Richardson 
1150bc44402fSTianfei Zhang 	if (spi_reg_read(dev, PKVL_A_MODE_STS, &value))
1151473c88f9SBruce Richardson 		return -EIO;
1152473c88f9SBruce Richardson 
1153bc44402fSTianfei Zhang 	dev_debug(dev, "PKVL A Mode Status 0x%x\n", value);
1154473c88f9SBruce Richardson 
1155bc44402fSTianfei Zhang 	if (value >= 0x100)
1156473c88f9SBruce Richardson 		return -EINVAL;
1157473c88f9SBruce Richardson 
1158bc44402fSTianfei Zhang 	if (spi_reg_read(dev, PKVL_B_MODE_STS, &value))
1159473c88f9SBruce Richardson 		return -EIO;
1160473c88f9SBruce Richardson 
1161bc44402fSTianfei Zhang 	dev_debug(dev, "PKVL B Mode Status 0x%x\n", value);
1162473c88f9SBruce Richardson 
1163bc44402fSTianfei Zhang 	if (value >= 0x100)
1164473c88f9SBruce Richardson 		return -EINVAL;
1165473c88f9SBruce Richardson 
1166473c88f9SBruce Richardson 	return 0;
1167473c88f9SBruce Richardson }
1168473c88f9SBruce Richardson 
fme_nios_spi_init(struct ifpga_feature * feature)1169473c88f9SBruce Richardson static int fme_nios_spi_init(struct ifpga_feature *feature)
1170473c88f9SBruce Richardson {
1171473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
1172473c88f9SBruce Richardson 	struct altera_spi_device *spi_master;
1173473c88f9SBruce Richardson 	struct intel_max10_device *max10;
11744a19f891STianfei Zhang 	struct ifpga_hw *hw;
11754a19f891STianfei Zhang 	struct opae_manager *mgr;
1176473c88f9SBruce Richardson 	int ret = 0;
1177473c88f9SBruce Richardson 
11784a19f891STianfei Zhang 	hw = fme->parent;
11794a19f891STianfei Zhang 	if (!hw)
11804a19f891STianfei Zhang 		return -ENODEV;
11814a19f891STianfei Zhang 
11824a19f891STianfei Zhang 	mgr = hw->adapter->mgr;
11834a19f891STianfei Zhang 	if (!mgr)
11844a19f891STianfei Zhang 		return -ENODEV;
11854a19f891STianfei Zhang 
1186473c88f9SBruce Richardson 	dev_info(fme, "FME SPI Master (NIOS) Init.\n");
1187473c88f9SBruce Richardson 	dev_debug(fme, "FME SPI base addr %p.\n",
1188473c88f9SBruce Richardson 			feature->addr);
1189473c88f9SBruce Richardson 	dev_debug(fme, "spi param=0x%llx\n",
1190473c88f9SBruce Richardson 			(unsigned long long)opae_readq(feature->addr + 0x8));
1191473c88f9SBruce Richardson 
1192473c88f9SBruce Richardson 	spi_master = altera_spi_alloc(feature->addr, TYPE_NIOS_SPI);
1193473c88f9SBruce Richardson 	if (!spi_master)
1194473c88f9SBruce Richardson 		return -ENODEV;
1195e41856b5SWei Huang 	init_spi_share_data(fme, spi_master);
1196473c88f9SBruce Richardson 
1197473c88f9SBruce Richardson 	/**
1198473c88f9SBruce Richardson 	 * 1. wait A10 NIOS initial finished and
1199473c88f9SBruce Richardson 	 * release the SPI master to Host
1200473c88f9SBruce Richardson 	 */
1201e41856b5SWei Huang 	if (spi_master->mutex)
1202e41856b5SWei Huang 		pthread_mutex_lock(spi_master->mutex);
1203e41856b5SWei Huang 
1204473c88f9SBruce Richardson 	ret = nios_spi_wait_init_done(spi_master);
1205473c88f9SBruce Richardson 	if (ret != 0) {
1206473c88f9SBruce Richardson 		dev_err(fme, "FME NIOS_SPI init fail\n");
12072414339cSWei Huang 		if (spi_master->mutex)
12082414339cSWei Huang 			pthread_mutex_unlock(spi_master->mutex);
1209473c88f9SBruce Richardson 		goto release_dev;
1210473c88f9SBruce Richardson 	}
1211473c88f9SBruce Richardson 
1212473c88f9SBruce Richardson 	dev_info(fme, "FME NIOS_SPI initial done\n");
1213473c88f9SBruce Richardson 
1214473c88f9SBruce Richardson 	/* 2. check if error occur? */
1215473c88f9SBruce Richardson 	if (nios_spi_check_error(spi_master))
1216473c88f9SBruce Richardson 		dev_info(fme, "NIOS_SPI INIT done, but found some error\n");
1217473c88f9SBruce Richardson 
1218e41856b5SWei Huang 	if (spi_master->mutex)
1219e41856b5SWei Huang 		pthread_mutex_unlock(spi_master->mutex);
1220e41856b5SWei Huang 
1221473c88f9SBruce Richardson 	/* 3. init the spi master*/
1222473c88f9SBruce Richardson 	altera_spi_init(spi_master);
1223473c88f9SBruce Richardson 
1224ca6eb0f7SWei Huang 	max10 = opae_zmalloc(sizeof(*max10));
1225ca6eb0f7SWei Huang 	if (!max10)
1226ca6eb0f7SWei Huang 		goto release_dev;
1227ca6eb0f7SWei Huang 
1228ca6eb0f7SWei Huang 	max10->spi_master = spi_master;
1229ca6eb0f7SWei Huang 	max10->type = M10_N3000;
1230ca6eb0f7SWei Huang 
1231ca6eb0f7SWei Huang 	max10->spi_tran_dev = spi_transaction_init(spi_master, 0);
1232ca6eb0f7SWei Huang 	if (!max10->spi_tran_dev) {
1233ca6eb0f7SWei Huang 		dev_err(fme, "%s spi tran init fail\n", __func__);
1234ca6eb0f7SWei Huang 		goto free_max10;
1235ca6eb0f7SWei Huang 	}
1236ca6eb0f7SWei Huang 
1237473c88f9SBruce Richardson 	/* init the max10 device */
1238ca6eb0f7SWei Huang 	ret = intel_max10_device_init(max10);
1239ca6eb0f7SWei Huang 	if (ret) {
1240473c88f9SBruce Richardson 		ret = -ENODEV;
1241473c88f9SBruce Richardson 		dev_err(fme, "max10 init fail\n");
1242ca6eb0f7SWei Huang 		goto release_spi_tran_dev;
1243473c88f9SBruce Richardson 	}
1244473c88f9SBruce Richardson 
1245e41856b5SWei Huang 	fme->max10_dev = max10;
12464a19f891STianfei Zhang 	max10->bus = hw->pci_data->bus;
1247473c88f9SBruce Richardson 	fme_get_board_interface(fme);
12484a19f891STianfei Zhang 	mgr->sensor_list = &max10->opae_sensor_list;
1249473c88f9SBruce Richardson 
1250473c88f9SBruce Richardson 	/* SPI self test */
12514a19f891STianfei Zhang 	if (spi_self_checking(max10))
1252473c88f9SBruce Richardson 		goto spi_fail;
1253473c88f9SBruce Richardson 
1254a05bd1b4SWei Huang 	ret = init_sec_mgr(fme);
1255a05bd1b4SWei Huang 	if (ret) {
1256a05bd1b4SWei Huang 		dev_err(fme, "security manager init fail\n");
1257a05bd1b4SWei Huang 		goto spi_fail;
1258a05bd1b4SWei Huang 	}
1259a05bd1b4SWei Huang 
1260473c88f9SBruce Richardson 	return ret;
1261473c88f9SBruce Richardson 
1262473c88f9SBruce Richardson spi_fail:
1263473c88f9SBruce Richardson 	intel_max10_device_remove(fme->max10_dev);
1264ca6eb0f7SWei Huang release_spi_tran_dev:
1265ca6eb0f7SWei Huang 	if (max10->spi_tran_dev)
1266ca6eb0f7SWei Huang 		spi_transaction_remove(max10->spi_tran_dev);
1267ca6eb0f7SWei Huang free_max10:
1268ca6eb0f7SWei Huang 	opae_free(max10);
1269473c88f9SBruce Richardson release_dev:
1270473c88f9SBruce Richardson 	altera_spi_release(spi_master);
1271473c88f9SBruce Richardson 	return -ENODEV;
1272473c88f9SBruce Richardson }
1273473c88f9SBruce Richardson 
fme_nios_spi_uinit(struct ifpga_feature * feature)1274473c88f9SBruce Richardson static void fme_nios_spi_uinit(struct ifpga_feature *feature)
1275473c88f9SBruce Richardson {
1276473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
1277473c88f9SBruce Richardson 
1278a05bd1b4SWei Huang 	release_sec_mgr(fme);
1279ca6eb0f7SWei Huang 	if (fme->max10_dev) {
1280473c88f9SBruce Richardson 		intel_max10_device_remove(fme->max10_dev);
1281ca6eb0f7SWei Huang 		opae_free(fme->max10_dev);
1282ca6eb0f7SWei Huang 	}
1283473c88f9SBruce Richardson }
1284473c88f9SBruce Richardson 
1285473c88f9SBruce Richardson struct ifpga_feature_ops fme_nios_spi_master_ops = {
1286473c88f9SBruce Richardson 	.init = fme_nios_spi_init,
1287473c88f9SBruce Richardson 	.uinit = fme_nios_spi_uinit,
1288473c88f9SBruce Richardson };
1289473c88f9SBruce Richardson 
i2c_mac_rom_test(struct altera_i2c_dev * dev)1290473c88f9SBruce Richardson static int i2c_mac_rom_test(struct altera_i2c_dev *dev)
1291473c88f9SBruce Richardson {
1292473c88f9SBruce Richardson 	char buf[20];
1293473c88f9SBruce Richardson 	int ret;
1294473c88f9SBruce Richardson 	char read_buf[20] = {0,};
1295473c88f9SBruce Richardson 	const char *string = "1a2b3c4d5e";
1296473c88f9SBruce Richardson 
1297473c88f9SBruce Richardson 	opae_memcpy(buf, string, strlen(string));
1298473c88f9SBruce Richardson 
1299473c88f9SBruce Richardson 	ret = at24_eeprom_write(dev, AT24512_SLAVE_ADDR, 0,
1300473c88f9SBruce Richardson 			(u8 *)buf, strlen(string));
1301473c88f9SBruce Richardson 	if (ret < 0) {
1302473c88f9SBruce Richardson 		dev_err(NULL, "write i2c error:%d\n", ret);
1303473c88f9SBruce Richardson 		return ret;
1304473c88f9SBruce Richardson 	}
1305473c88f9SBruce Richardson 
1306473c88f9SBruce Richardson 	ret = at24_eeprom_read(dev, AT24512_SLAVE_ADDR, 0,
1307473c88f9SBruce Richardson 			(u8 *)read_buf, strlen(string));
1308473c88f9SBruce Richardson 	if (ret < 0) {
1309473c88f9SBruce Richardson 		dev_err(NULL, "read i2c error:%d\n", ret);
1310473c88f9SBruce Richardson 		return ret;
1311473c88f9SBruce Richardson 	}
1312473c88f9SBruce Richardson 
1313473c88f9SBruce Richardson 	if (memcmp(buf, read_buf, strlen(string))) {
1314ca6eb0f7SWei Huang 		dev_info(NULL, "%s test fail!\n", __func__);
1315473c88f9SBruce Richardson 		return -EFAULT;
1316473c88f9SBruce Richardson 	}
1317473c88f9SBruce Richardson 
1318473c88f9SBruce Richardson 	dev_info(NULL, "%s test successful\n", __func__);
1319473c88f9SBruce Richardson 
1320473c88f9SBruce Richardson 	return 0;
1321473c88f9SBruce Richardson }
1322473c88f9SBruce Richardson 
init_i2c_mutex(struct ifpga_fme_hw * fme)1323e41856b5SWei Huang static void init_i2c_mutex(struct ifpga_fme_hw *fme)
1324e41856b5SWei Huang {
1325e41856b5SWei Huang 	struct ifpga_hw *hw = (struct ifpga_hw *)fme->parent;
1326e41856b5SWei Huang 	struct altera_i2c_dev *i2c_dev;
1327e41856b5SWei Huang 	opae_share_data *sd = NULL;
1328e41856b5SWei Huang 
1329e41856b5SWei Huang 	if (fme->i2c_master) {
1330e41856b5SWei Huang 		i2c_dev = (struct altera_i2c_dev *)fme->i2c_master;
1331e41856b5SWei Huang 		if (hw && hw->adapter && hw->adapter->shm.ptr) {
1332e41856b5SWei Huang 			dev_info(NULL, "use multi-process mutex in i2c\n");
1333e41856b5SWei Huang 			sd = (opae_share_data *)hw->adapter->shm.ptr;
1334e41856b5SWei Huang 			i2c_dev->mutex = &sd->i2c_mutex;
1335e41856b5SWei Huang 		} else {
1336e41856b5SWei Huang 			dev_info(NULL, "use multi-thread mutex in i2c\n");
1337e41856b5SWei Huang 			i2c_dev->mutex = &i2c_dev->lock;
1338e41856b5SWei Huang 		}
1339e41856b5SWei Huang 	}
1340e41856b5SWei Huang }
1341e41856b5SWei Huang 
fme_i2c_init(struct ifpga_feature * feature)1342473c88f9SBruce Richardson static int fme_i2c_init(struct ifpga_feature *feature)
1343473c88f9SBruce Richardson {
1344473c88f9SBruce Richardson 	struct feature_fme_i2c *i2c;
1345473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
1346473c88f9SBruce Richardson 
1347473c88f9SBruce Richardson 	i2c = (struct feature_fme_i2c *)feature->addr;
1348473c88f9SBruce Richardson 
1349473c88f9SBruce Richardson 	dev_info(NULL, "FME I2C Master Init.\n");
1350473c88f9SBruce Richardson 
1351473c88f9SBruce Richardson 	fme->i2c_master = altera_i2c_probe(i2c);
1352473c88f9SBruce Richardson 	if (!fme->i2c_master)
1353473c88f9SBruce Richardson 		return -ENODEV;
1354473c88f9SBruce Richardson 
1355e41856b5SWei Huang 	init_i2c_mutex(fme);
1356e41856b5SWei Huang 
1357473c88f9SBruce Richardson 	/* MAC ROM self test */
1358473c88f9SBruce Richardson 	i2c_mac_rom_test(fme->i2c_master);
1359473c88f9SBruce Richardson 
1360473c88f9SBruce Richardson 	return 0;
1361473c88f9SBruce Richardson }
1362473c88f9SBruce Richardson 
fme_i2c_uninit(struct ifpga_feature * feature)1363473c88f9SBruce Richardson static void fme_i2c_uninit(struct ifpga_feature *feature)
1364473c88f9SBruce Richardson {
1365473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
1366473c88f9SBruce Richardson 
1367473c88f9SBruce Richardson 	altera_i2c_remove(fme->i2c_master);
1368473c88f9SBruce Richardson }
1369473c88f9SBruce Richardson 
1370473c88f9SBruce Richardson struct ifpga_feature_ops fme_i2c_master_ops = {
1371473c88f9SBruce Richardson 	.init = fme_i2c_init,
1372473c88f9SBruce Richardson 	.uinit = fme_i2c_uninit,
1373473c88f9SBruce Richardson };
1374473c88f9SBruce Richardson 
fme_eth_group_init(struct ifpga_feature * feature)1375473c88f9SBruce Richardson static int fme_eth_group_init(struct ifpga_feature *feature)
1376473c88f9SBruce Richardson {
1377473c88f9SBruce Richardson 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
1378473c88f9SBruce Richardson 	struct eth_group_device *dev;
1379473c88f9SBruce Richardson 
1380473c88f9SBruce Richardson 	dev = (struct eth_group_device *)eth_group_probe(feature->addr);
1381473c88f9SBruce Richardson 	if (!dev)
1382473c88f9SBruce Richardson 		return -ENODEV;
1383473c88f9SBruce Richardson 
1384473c88f9SBruce Richardson 	fme->eth_dev[dev->group_id] = dev;
1385473c88f9SBruce Richardson 
1386473c88f9SBruce Richardson 	fme->eth_group_region[dev->group_id].addr =
1387473c88f9SBruce Richardson 		feature->addr;
1388473c88f9SBruce Richardson 	fme->eth_group_region[dev->group_id].phys_addr =
1389473c88f9SBruce Richardson 		feature->phys_addr;
1390473c88f9SBruce Richardson 	fme->eth_group_region[dev->group_id].len =
1391473c88f9SBruce Richardson 		feature->size;
1392473c88f9SBruce Richardson 
1393473c88f9SBruce Richardson 	fme->nums_eth_dev++;
1394473c88f9SBruce Richardson 
1395473c88f9SBruce Richardson 	dev_info(NULL, "FME PHY Group %d Init.\n", dev->group_id);
1396473c88f9SBruce Richardson 	dev_info(NULL, "found %d eth group, addr %p phys_addr 0x%llx len %u\n",
1397473c88f9SBruce Richardson 			dev->group_id, feature->addr,
1398473c88f9SBruce Richardson 			(unsigned long long)feature->phys_addr,
1399473c88f9SBruce Richardson 			feature->size);
1400473c88f9SBruce Richardson 
1401473c88f9SBruce Richardson 	return 0;
1402473c88f9SBruce Richardson }
1403473c88f9SBruce Richardson 
fme_eth_group_uinit(struct ifpga_feature * feature)1404473c88f9SBruce Richardson static void fme_eth_group_uinit(struct ifpga_feature *feature)
1405473c88f9SBruce Richardson {
1406473c88f9SBruce Richardson 	UNUSED(feature);
1407473c88f9SBruce Richardson }
1408473c88f9SBruce Richardson 
1409473c88f9SBruce Richardson struct ifpga_feature_ops fme_eth_group_ops = {
1410473c88f9SBruce Richardson 	.init = fme_eth_group_init,
1411473c88f9SBruce Richardson 	.uinit = fme_eth_group_uinit,
1412473c88f9SBruce Richardson };
1413473c88f9SBruce Richardson 
fme_mgr_read_mac_rom(struct ifpga_fme_hw * fme,int offset,void * buf,int size)1414473c88f9SBruce Richardson int fme_mgr_read_mac_rom(struct ifpga_fme_hw *fme, int offset,
1415473c88f9SBruce Richardson 		void *buf, int size)
1416473c88f9SBruce Richardson {
1417473c88f9SBruce Richardson 	struct altera_i2c_dev *dev;
1418473c88f9SBruce Richardson 
1419473c88f9SBruce Richardson 	dev = fme->i2c_master;
1420473c88f9SBruce Richardson 	if (!dev)
1421473c88f9SBruce Richardson 		return -ENODEV;
1422473c88f9SBruce Richardson 
1423473c88f9SBruce Richardson 	return at24_eeprom_read(dev, AT24512_SLAVE_ADDR, offset, buf, size);
1424473c88f9SBruce Richardson }
1425473c88f9SBruce Richardson 
fme_mgr_write_mac_rom(struct ifpga_fme_hw * fme,int offset,void * buf,int size)1426473c88f9SBruce Richardson int fme_mgr_write_mac_rom(struct ifpga_fme_hw *fme, int offset,
1427473c88f9SBruce Richardson 		void *buf, int size)
1428473c88f9SBruce Richardson {
1429473c88f9SBruce Richardson 	struct altera_i2c_dev *dev;
1430473c88f9SBruce Richardson 
1431473c88f9SBruce Richardson 	dev = fme->i2c_master;
1432473c88f9SBruce Richardson 	if (!dev)
1433473c88f9SBruce Richardson 		return -ENODEV;
1434473c88f9SBruce Richardson 
1435473c88f9SBruce Richardson 	return at24_eeprom_write(dev, AT24512_SLAVE_ADDR, offset, buf, size);
1436473c88f9SBruce Richardson }
1437473c88f9SBruce Richardson 
get_eth_group_dev(struct ifpga_fme_hw * fme,u8 group_id)1438473c88f9SBruce Richardson static struct eth_group_device *get_eth_group_dev(struct ifpga_fme_hw *fme,
1439473c88f9SBruce Richardson 		u8 group_id)
1440473c88f9SBruce Richardson {
1441473c88f9SBruce Richardson 	struct eth_group_device *dev;
1442473c88f9SBruce Richardson 
1443473c88f9SBruce Richardson 	if (group_id > (MAX_ETH_GROUP_DEVICES - 1))
1444473c88f9SBruce Richardson 		return NULL;
1445473c88f9SBruce Richardson 
1446473c88f9SBruce Richardson 	dev = (struct eth_group_device *)fme->eth_dev[group_id];
1447473c88f9SBruce Richardson 	if (!dev)
1448473c88f9SBruce Richardson 		return NULL;
1449473c88f9SBruce Richardson 
1450473c88f9SBruce Richardson 	if (dev->status != ETH_GROUP_DEV_ATTACHED)
1451473c88f9SBruce Richardson 		return NULL;
1452473c88f9SBruce Richardson 
1453473c88f9SBruce Richardson 	return dev;
1454473c88f9SBruce Richardson }
1455473c88f9SBruce Richardson 
fme_mgr_get_eth_group_nums(struct ifpga_fme_hw * fme)1456473c88f9SBruce Richardson int fme_mgr_get_eth_group_nums(struct ifpga_fme_hw *fme)
1457473c88f9SBruce Richardson {
1458473c88f9SBruce Richardson 	return fme->nums_eth_dev;
1459473c88f9SBruce Richardson }
1460473c88f9SBruce Richardson 
fme_mgr_get_eth_group_info(struct ifpga_fme_hw * fme,u8 group_id,struct opae_eth_group_info * info)1461473c88f9SBruce Richardson int fme_mgr_get_eth_group_info(struct ifpga_fme_hw *fme,
1462473c88f9SBruce Richardson 		u8 group_id, struct opae_eth_group_info *info)
1463473c88f9SBruce Richardson {
1464473c88f9SBruce Richardson 	struct eth_group_device *dev;
1465473c88f9SBruce Richardson 
1466473c88f9SBruce Richardson 	dev = get_eth_group_dev(fme, group_id);
1467473c88f9SBruce Richardson 	if (!dev)
1468473c88f9SBruce Richardson 		return -ENODEV;
1469473c88f9SBruce Richardson 
1470473c88f9SBruce Richardson 	info->group_id = group_id;
1471473c88f9SBruce Richardson 	info->speed = dev->speed;
1472473c88f9SBruce Richardson 	info->nums_of_mac = dev->mac_num;
1473473c88f9SBruce Richardson 	info->nums_of_phy = dev->phy_num;
1474473c88f9SBruce Richardson 
1475473c88f9SBruce Richardson 	return 0;
1476473c88f9SBruce Richardson }
1477473c88f9SBruce Richardson 
fme_mgr_eth_group_read_reg(struct ifpga_fme_hw * fme,u8 group_id,u8 type,u8 index,u16 addr,u32 * data)1478473c88f9SBruce Richardson int fme_mgr_eth_group_read_reg(struct ifpga_fme_hw *fme, u8 group_id,
1479473c88f9SBruce Richardson 		u8 type, u8 index, u16 addr, u32 *data)
1480473c88f9SBruce Richardson {
1481473c88f9SBruce Richardson 	struct eth_group_device *dev;
1482473c88f9SBruce Richardson 
1483473c88f9SBruce Richardson 	dev = get_eth_group_dev(fme, group_id);
1484473c88f9SBruce Richardson 	if (!dev)
1485473c88f9SBruce Richardson 		return -ENODEV;
1486473c88f9SBruce Richardson 
1487473c88f9SBruce Richardson 	return eth_group_read_reg(dev, type, index, addr, data);
1488473c88f9SBruce Richardson }
1489473c88f9SBruce Richardson 
fme_mgr_eth_group_write_reg(struct ifpga_fme_hw * fme,u8 group_id,u8 type,u8 index,u16 addr,u32 data)1490473c88f9SBruce Richardson int fme_mgr_eth_group_write_reg(struct ifpga_fme_hw *fme, u8 group_id,
1491473c88f9SBruce Richardson 		u8 type, u8 index, u16 addr, u32 data)
1492473c88f9SBruce Richardson {
1493473c88f9SBruce Richardson 	struct eth_group_device *dev;
1494473c88f9SBruce Richardson 
1495473c88f9SBruce Richardson 	dev = get_eth_group_dev(fme, group_id);
1496473c88f9SBruce Richardson 	if (!dev)
1497473c88f9SBruce Richardson 		return -ENODEV;
1498473c88f9SBruce Richardson 
1499473c88f9SBruce Richardson 	return eth_group_write_reg(dev, type, index, addr, data);
1500473c88f9SBruce Richardson }
1501473c88f9SBruce Richardson 
fme_get_eth_group_speed(struct ifpga_fme_hw * fme,u8 group_id)1502473c88f9SBruce Richardson static int fme_get_eth_group_speed(struct ifpga_fme_hw *fme,
1503473c88f9SBruce Richardson 		u8 group_id)
1504473c88f9SBruce Richardson {
1505473c88f9SBruce Richardson 	struct eth_group_device *dev;
1506473c88f9SBruce Richardson 
1507473c88f9SBruce Richardson 	dev = get_eth_group_dev(fme, group_id);
1508473c88f9SBruce Richardson 	if (!dev)
1509473c88f9SBruce Richardson 		return -ENODEV;
1510473c88f9SBruce Richardson 
1511473c88f9SBruce Richardson 	return dev->speed;
1512473c88f9SBruce Richardson }
1513473c88f9SBruce Richardson 
fme_mgr_get_retimer_info(struct ifpga_fme_hw * fme,struct opae_retimer_info * info)1514473c88f9SBruce Richardson int fme_mgr_get_retimer_info(struct ifpga_fme_hw *fme,
1515473c88f9SBruce Richardson 		struct opae_retimer_info *info)
1516473c88f9SBruce Richardson {
1517473c88f9SBruce Richardson 	struct intel_max10_device *dev;
1518473c88f9SBruce Richardson 
1519473c88f9SBruce Richardson 	dev = (struct intel_max10_device *)fme->max10_dev;
1520473c88f9SBruce Richardson 	if (!dev)
1521473c88f9SBruce Richardson 		return -ENODEV;
1522473c88f9SBruce Richardson 
1523473c88f9SBruce Richardson 	info->nums_retimer = fme->board_info.nums_of_retimer;
1524473c88f9SBruce Richardson 	info->ports_per_retimer = fme->board_info.ports_per_retimer;
1525473c88f9SBruce Richardson 	info->nums_fvl = fme->board_info.nums_of_fvl;
1526473c88f9SBruce Richardson 	info->ports_per_fvl = fme->board_info.ports_per_fvl;
1527473c88f9SBruce Richardson 
1528473c88f9SBruce Richardson 	/* The speed of PKVL is identical the eth group's speed */
1529473c88f9SBruce Richardson 	info->support_speed = fme_get_eth_group_speed(fme,
1530473c88f9SBruce Richardson 			LINE_SIDE_GROUP_ID);
1531473c88f9SBruce Richardson 
1532473c88f9SBruce Richardson 	return 0;
1533473c88f9SBruce Richardson }
1534473c88f9SBruce Richardson 
fme_mgr_get_retimer_status(struct ifpga_fme_hw * fme,struct opae_retimer_status * status)1535473c88f9SBruce Richardson int fme_mgr_get_retimer_status(struct ifpga_fme_hw *fme,
1536473c88f9SBruce Richardson 		struct opae_retimer_status *status)
1537473c88f9SBruce Richardson {
1538473c88f9SBruce Richardson 	struct intel_max10_device *dev;
1539473c88f9SBruce Richardson 	unsigned int val;
1540473c88f9SBruce Richardson 
1541473c88f9SBruce Richardson 	dev = (struct intel_max10_device *)fme->max10_dev;
1542473c88f9SBruce Richardson 	if (!dev)
1543473c88f9SBruce Richardson 		return -ENODEV;
1544473c88f9SBruce Richardson 
15454a19f891STianfei Zhang 	if (max10_sys_read(dev, PKVL_LINK_STATUS, &val)) {
1546473c88f9SBruce Richardson 		dev_err(dev, "%s: read pkvl status fail\n", __func__);
1547473c88f9SBruce Richardson 		return -EINVAL;
1548473c88f9SBruce Richardson 	}
1549473c88f9SBruce Richardson 
1550473c88f9SBruce Richardson 	/* The speed of PKVL is identical the eth group's speed */
1551473c88f9SBruce Richardson 	status->speed = fme_get_eth_group_speed(fme,
1552473c88f9SBruce Richardson 			LINE_SIDE_GROUP_ID);
1553473c88f9SBruce Richardson 
1554473c88f9SBruce Richardson 	status->line_link_bitmap = val;
1555473c88f9SBruce Richardson 
1556473c88f9SBruce Richardson 	dev_debug(dev, "get retimer status: speed:%d. line_link_bitmap:0x%x\n",
1557473c88f9SBruce Richardson 			status->speed,
1558473c88f9SBruce Richardson 			status->line_link_bitmap);
1559473c88f9SBruce Richardson 
1560473c88f9SBruce Richardson 	return 0;
1561473c88f9SBruce Richardson }
156219118989STianfei Zhang 
fme_mgr_get_sensor_value(struct ifpga_fme_hw * fme,struct opae_sensor_info * sensor,unsigned int * value)156319118989STianfei Zhang int fme_mgr_get_sensor_value(struct ifpga_fme_hw *fme,
156419118989STianfei Zhang 		struct opae_sensor_info *sensor,
156519118989STianfei Zhang 		unsigned int *value)
156619118989STianfei Zhang {
156719118989STianfei Zhang 	struct intel_max10_device *dev;
156819118989STianfei Zhang 
156919118989STianfei Zhang 	dev = (struct intel_max10_device *)fme->max10_dev;
157019118989STianfei Zhang 	if (!dev)
157119118989STianfei Zhang 		return -ENODEV;
157219118989STianfei Zhang 
15734a19f891STianfei Zhang 	if (max10_sys_read(dev, sensor->value_reg, value)) {
157419118989STianfei Zhang 		dev_err(dev, "%s: read sensor value register 0x%x fail\n",
157519118989STianfei Zhang 				__func__, sensor->value_reg);
157619118989STianfei Zhang 		return -EINVAL;
157719118989STianfei Zhang 	}
157819118989STianfei Zhang 
157919118989STianfei Zhang 	*value *= sensor->multiplier;
158019118989STianfei Zhang 
158119118989STianfei Zhang 	return 0;
158219118989STianfei Zhang }
1583ca6eb0f7SWei Huang 
fme_pmci_init(struct ifpga_feature * feature)1584ca6eb0f7SWei Huang static int fme_pmci_init(struct ifpga_feature *feature)
1585ca6eb0f7SWei Huang {
1586ca6eb0f7SWei Huang 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
1587ca6eb0f7SWei Huang 	struct intel_max10_device *max10;
1588ca6eb0f7SWei Huang 	struct ifpga_hw *hw;
1589ca6eb0f7SWei Huang 	struct opae_manager *mgr;
1590ca6eb0f7SWei Huang 	opae_share_data *sd = NULL;
1591ca6eb0f7SWei Huang 	int ret = 0;
1592ca6eb0f7SWei Huang 
1593ca6eb0f7SWei Huang 	hw = fme->parent;
1594*b6e029cfSWei Huang 	if (!hw || !hw->adapter)
1595ca6eb0f7SWei Huang 		return -ENODEV;
1596ca6eb0f7SWei Huang 
1597ca6eb0f7SWei Huang 	mgr = hw->adapter->mgr;
1598ca6eb0f7SWei Huang 	if (!mgr)
1599ca6eb0f7SWei Huang 		return -ENODEV;
1600ca6eb0f7SWei Huang 
1601ca6eb0f7SWei Huang 	dev_info(fme, "FME PMCI Init.\n");
1602ca6eb0f7SWei Huang 	dev_debug(fme, "FME PMCI base addr %p.\n",
1603ca6eb0f7SWei Huang 			feature->addr);
1604ca6eb0f7SWei Huang 
1605ca6eb0f7SWei Huang 	max10 = opae_zmalloc(sizeof(*max10));
1606ca6eb0f7SWei Huang 	if (!max10)
1607ca6eb0f7SWei Huang 		return -ENOMEM;
1608ca6eb0f7SWei Huang 
1609ca6eb0f7SWei Huang 	max10->type = M10_N6000;
1610ca6eb0f7SWei Huang 	max10->mmio = feature->addr;
1611*b6e029cfSWei Huang 	if (hw->adapter->shm.ptr) {
1612ca6eb0f7SWei Huang 		sd = (opae_share_data *)hw->adapter->shm.ptr;
1613ca6eb0f7SWei Huang 		max10->bmc_ops.mutex = &sd->spi_mutex;
1614ca6eb0f7SWei Huang 	} else {
1615ca6eb0f7SWei Huang 		max10->bmc_ops.mutex = NULL;
1616ca6eb0f7SWei Huang 	}
1617ca6eb0f7SWei Huang 
1618ca6eb0f7SWei Huang 	/* init the max10 device */
1619ca6eb0f7SWei Huang 	ret = intel_max10_device_init(max10);
1620ca6eb0f7SWei Huang 	if (ret) {
1621ca6eb0f7SWei Huang 		dev_err(fme, "max10 init fail\n");
1622ca6eb0f7SWei Huang 		goto free_max10;
1623ca6eb0f7SWei Huang 	}
1624ca6eb0f7SWei Huang 
1625ca6eb0f7SWei Huang 	fme->max10_dev = max10;
1626ca6eb0f7SWei Huang 	max10->bus = hw->pci_data->bus;
1627ca6eb0f7SWei Huang 	fme_get_board_interface(fme);
1628ca6eb0f7SWei Huang 	mgr->sensor_list = &max10->opae_sensor_list;
1629ca6eb0f7SWei Huang 
1630ca6eb0f7SWei Huang 	ret = init_sec_mgr(fme);
1631ca6eb0f7SWei Huang 	if (ret) {
1632ca6eb0f7SWei Huang 		dev_err(fme, "security manager init fail\n");
1633ca6eb0f7SWei Huang 		goto release_max10;
1634ca6eb0f7SWei Huang 	}
1635ca6eb0f7SWei Huang 
1636ca6eb0f7SWei Huang 	return ret;
1637ca6eb0f7SWei Huang 
1638ca6eb0f7SWei Huang release_max10:
1639ca6eb0f7SWei Huang 	intel_max10_device_remove(max10);
1640ca6eb0f7SWei Huang free_max10:
1641ca6eb0f7SWei Huang 	opae_free(max10);
1642ca6eb0f7SWei Huang 
1643ca6eb0f7SWei Huang 	return ret;
1644ca6eb0f7SWei Huang }
1645ca6eb0f7SWei Huang 
fme_pmci_uinit(struct ifpga_feature * feature)1646ca6eb0f7SWei Huang static void fme_pmci_uinit(struct ifpga_feature *feature)
1647ca6eb0f7SWei Huang {
1648ca6eb0f7SWei Huang 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
1649ca6eb0f7SWei Huang 
1650ca6eb0f7SWei Huang 	release_sec_mgr(fme);
1651ca6eb0f7SWei Huang 	if (fme->max10_dev) {
1652ca6eb0f7SWei Huang 		intel_max10_device_remove(fme->max10_dev);
1653ca6eb0f7SWei Huang 		opae_free(fme->max10_dev);
1654ca6eb0f7SWei Huang 	}
1655ca6eb0f7SWei Huang }
1656ca6eb0f7SWei Huang 
1657ca6eb0f7SWei Huang struct ifpga_feature_ops fme_pmci_ops = {
1658ca6eb0f7SWei Huang 	.init = fme_pmci_init,
1659ca6eb0f7SWei Huang 	.uinit = fme_pmci_uinit,
1660ca6eb0f7SWei Huang };
1661b74ee6c8SWei Huang 
fme_mgr_read_flash(struct ifpga_fme_hw * fme,u32 address,u32 size,void * buf)1662b74ee6c8SWei Huang int fme_mgr_read_flash(struct ifpga_fme_hw *fme, u32 address,
1663b74ee6c8SWei Huang 		u32 size, void *buf)
1664b74ee6c8SWei Huang {
1665b74ee6c8SWei Huang 	struct intel_max10_device *max10 = fme->max10_dev;
1666b74ee6c8SWei Huang 
1667b74ee6c8SWei Huang 	return opae_read_flash(max10, address, size, buf);
1668b74ee6c8SWei Huang }
1669