xref: /dpdk/drivers/raw/ifpga/base/opae_intel_max10.c (revision d28809c27d2dae063231bee4e8332095476812f3)
1473c88f9SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2473c88f9SBruce Richardson  * Copyright(c) 2010-2019 Intel Corporation
3473c88f9SBruce Richardson  */
4473c88f9SBruce Richardson 
5473c88f9SBruce Richardson #include "opae_intel_max10.h"
6e1defba4STianfei Zhang #include <libfdt.h>
7ca6eb0f7SWei Huang #include "opae_osdep.h"
8473c88f9SBruce Richardson 
911986223SStephen Hemminger #ifndef TAILQ_FOREACH_SAFE
1011986223SStephen Hemminger #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
1111986223SStephen Hemminger 	for ((var) = TAILQ_FIRST((head)); \
1211986223SStephen Hemminger 		(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
1311986223SStephen Hemminger 	(var) = (tvar))
1411986223SStephen Hemminger #endif
1511986223SStephen Hemminger 
164a19f891STianfei Zhang int max10_sys_read(struct intel_max10_device *dev,
174a19f891STianfei Zhang 	unsigned int offset, unsigned int *val)
1871da60b8STianfei Zhang {
19ca6eb0f7SWei Huang 	if (!dev || !dev->ops->reg_read)
2071da60b8STianfei Zhang 		return -ENODEV;
2171da60b8STianfei Zhang 
22ca6eb0f7SWei Huang 	return dev->ops->reg_read(dev, dev->csr->base + offset, val);
2371da60b8STianfei Zhang }
2471da60b8STianfei Zhang 
254a19f891STianfei Zhang int max10_sys_write(struct intel_max10_device *dev,
264a19f891STianfei Zhang 	unsigned int offset, unsigned int val)
2771da60b8STianfei Zhang {
28ca6eb0f7SWei Huang 	if (!dev || !dev->ops->reg_write)
2971da60b8STianfei Zhang 		return -ENODEV;
3071da60b8STianfei Zhang 
31ca6eb0f7SWei Huang 	return dev->ops->reg_write(dev, dev->csr->base + offset, val);
32ca6eb0f7SWei Huang }
33ca6eb0f7SWei Huang 
34ca6eb0f7SWei Huang int max10_reg_read(struct intel_max10_device *dev,
35ca6eb0f7SWei Huang 	unsigned int offset, unsigned int *val)
36ca6eb0f7SWei Huang {
37ca6eb0f7SWei Huang 	if (!dev || !dev->ops->reg_read)
38ca6eb0f7SWei Huang 		return -ENODEV;
39ca6eb0f7SWei Huang 
40ca6eb0f7SWei Huang 	return dev->ops->reg_read(dev, offset, val);
41ca6eb0f7SWei Huang }
42ca6eb0f7SWei Huang 
43ca6eb0f7SWei Huang int max10_reg_write(struct intel_max10_device *dev,
44ca6eb0f7SWei Huang 	unsigned int offset, unsigned int val)
45ca6eb0f7SWei Huang {
46ca6eb0f7SWei Huang 	if (!dev || !dev->ops->reg_write)
47ca6eb0f7SWei Huang 		return -ENODEV;
48ca6eb0f7SWei Huang 
49ca6eb0f7SWei Huang 	return dev->ops->reg_write(dev, offset, val);
5071da60b8STianfei Zhang }
5171da60b8STianfei Zhang 
52a05bd1b4SWei Huang int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset,
53a05bd1b4SWei Huang 					unsigned int msk, unsigned int val)
54a05bd1b4SWei Huang {
55a05bd1b4SWei Huang 	int ret = 0;
56a05bd1b4SWei Huang 	unsigned int temp = 0;
57a05bd1b4SWei Huang 
58a05bd1b4SWei Huang 	ret = max10_sys_read(dev, offset, &temp);
59a05bd1b4SWei Huang 	if (ret < 0)
60a05bd1b4SWei Huang 		return ret;
61a05bd1b4SWei Huang 
62a05bd1b4SWei Huang 	temp &= ~msk;
63a05bd1b4SWei Huang 	temp |= val & msk;
64a05bd1b4SWei Huang 
65a05bd1b4SWei Huang 	return max10_sys_write(dev, offset, temp);
66a05bd1b4SWei Huang }
67a05bd1b4SWei Huang 
68b74ee6c8SWei Huang static int n3000_bulk_raw_write(struct intel_max10_device *dev, uint32_t addr,
69b74ee6c8SWei Huang 	void *buf, uint32_t len)
70b74ee6c8SWei Huang {
71b74ee6c8SWei Huang 	uint32_t v = 0;
72b74ee6c8SWei Huang 	uint32_t i = 0;
73b74ee6c8SWei Huang 	char *p = buf;
74b74ee6c8SWei Huang 	int ret = 0;
75b74ee6c8SWei Huang 
76b74ee6c8SWei Huang 	len = IFPGA_ALIGN(len, 4);
77b74ee6c8SWei Huang 
78b74ee6c8SWei Huang 	for (i = 0; i < len; i += 4) {
79b74ee6c8SWei Huang 		v = *(uint32_t *)(p + i);
80b74ee6c8SWei Huang 		ret = max10_reg_write(dev, addr + i, v);
81b74ee6c8SWei Huang 		if (ret < 0) {
82b74ee6c8SWei Huang 			dev_err(dev,
83b74ee6c8SWei Huang 				"Failed to write to staging area 0x%08x [e:%d]\n",
84b74ee6c8SWei Huang 				addr + i, ret);
85b74ee6c8SWei Huang 			return ret;
86b74ee6c8SWei Huang 		}
87b74ee6c8SWei Huang 	}
88b74ee6c8SWei Huang 
89b74ee6c8SWei Huang 	return 0;
90b74ee6c8SWei Huang }
91b74ee6c8SWei Huang 
92b74ee6c8SWei Huang static int n3000_bulk_raw_read(struct intel_max10_device *dev,
93b74ee6c8SWei Huang 		uint32_t addr, void *buf, uint32_t len)
94b74ee6c8SWei Huang {
95b74ee6c8SWei Huang 	u32 v, i;
96b74ee6c8SWei Huang 	char *p = buf;
97b74ee6c8SWei Huang 	int ret;
98b74ee6c8SWei Huang 
99b74ee6c8SWei Huang 	len = IFPGA_ALIGN(len, 4);
100b74ee6c8SWei Huang 
101b74ee6c8SWei Huang 	for (i = 0; i < len; i += 4) {
102b74ee6c8SWei Huang 		ret = max10_reg_read(dev, addr + i, &v);
103b74ee6c8SWei Huang 		if (ret < 0) {
104b74ee6c8SWei Huang 			dev_err(dev,
105b74ee6c8SWei Huang 				"Failed to write to staging area 0x%08x [e:%d]\n",
106b74ee6c8SWei Huang 				addr + i, ret);
107b74ee6c8SWei Huang 			return ret;
108b74ee6c8SWei Huang 		}
109b74ee6c8SWei Huang 		*(u32 *)(p + i) = v;
110b74ee6c8SWei Huang 	}
111b74ee6c8SWei Huang 
112b74ee6c8SWei Huang 	return 0;
113b74ee6c8SWei Huang }
114b74ee6c8SWei Huang 
115b74ee6c8SWei Huang static int n3000_flash_read(struct intel_max10_device *dev,
116b74ee6c8SWei Huang 		u32 addr, void *buf, u32 size)
117b74ee6c8SWei Huang {
118b74ee6c8SWei Huang 	if (!dev->raw_blk_ops.read_blk)
119b74ee6c8SWei Huang 		return -ENODEV;
120b74ee6c8SWei Huang 
121b74ee6c8SWei Huang 	return dev->raw_blk_ops.read_blk(dev, addr, buf, size);
122b74ee6c8SWei Huang }
123b74ee6c8SWei Huang 
124b74ee6c8SWei Huang static int n3000_flash_write(struct intel_max10_device *dev,
125b74ee6c8SWei Huang 		u32 addr, void *buf, u32 size)
126b74ee6c8SWei Huang {
127b74ee6c8SWei Huang 	if (!dev->raw_blk_ops.write_blk)
128b74ee6c8SWei Huang 		return -ENODEV;
129b74ee6c8SWei Huang 
130b74ee6c8SWei Huang 	return dev->raw_blk_ops.write_blk(dev, addr, buf, size);
131b74ee6c8SWei Huang }
132b74ee6c8SWei Huang 
133b74ee6c8SWei Huang static u32
134b74ee6c8SWei Huang pmci_get_write_space(struct intel_max10_device *dev, u32 size)
135b74ee6c8SWei Huang {
136b74ee6c8SWei Huang 	u32 count, val;
137b74ee6c8SWei Huang 	int ret;
138b74ee6c8SWei Huang 
139b74ee6c8SWei Huang 	ret = opae_readl_poll_timeout(dev->mmio + PMCI_FLASH_CTRL, val,
140b74ee6c8SWei Huang 				GET_FIELD(PMCI_FLASH_FIFO_SPACE, val) ==
141b74ee6c8SWei Huang 				PMCI_FIFO_MAX_WORDS,
142b74ee6c8SWei Huang 				PMCI_FLASH_INT_US, PMCI_FLASH_TIMEOUT_US);
143b74ee6c8SWei Huang 	if (ret == -ETIMEDOUT)
144b74ee6c8SWei Huang 		return 0;
145b74ee6c8SWei Huang 
146b74ee6c8SWei Huang 	count = GET_FIELD(PMCI_FLASH_FIFO_SPACE, val) * 4;
147b74ee6c8SWei Huang 
148b74ee6c8SWei Huang 	return (size > count) ? count : size;
149b74ee6c8SWei Huang }
150b74ee6c8SWei Huang 
151b74ee6c8SWei Huang static void pmci_write_fifo(void __iomem *base, char *buf, size_t count)
152b74ee6c8SWei Huang {
153b74ee6c8SWei Huang 	size_t i;
154b74ee6c8SWei Huang 	u32 val;
155b74ee6c8SWei Huang 
156b74ee6c8SWei Huang 	for (i = 0; i < count/4 ; i++) {
157b74ee6c8SWei Huang 		val = *(u32 *)(buf + i * 4);
158b74ee6c8SWei Huang 		writel(val, base);
159b74ee6c8SWei Huang 	}
160b74ee6c8SWei Huang }
161b74ee6c8SWei Huang 
162b74ee6c8SWei Huang static void pmci_read_fifo(void __iomem *base, char *buf, size_t count)
163b74ee6c8SWei Huang {
164b74ee6c8SWei Huang 	size_t i;
165b74ee6c8SWei Huang 	u32 val;
166b74ee6c8SWei Huang 
167b74ee6c8SWei Huang 	for (i = 0; i < count/4; i++) {
168b74ee6c8SWei Huang 		val = readl(base);
169b74ee6c8SWei Huang 		*(u32 *)(buf + i * 4) = val;
170b74ee6c8SWei Huang 	}
171b74ee6c8SWei Huang }
172b74ee6c8SWei Huang 
173b74ee6c8SWei Huang static int
174b74ee6c8SWei Huang __pmci_flash_bulk_write(struct intel_max10_device *dev, u32 addr,
175b74ee6c8SWei Huang 		void *buf, u32 size)
176b74ee6c8SWei Huang {
177b74ee6c8SWei Huang 	UNUSED(addr);
178b74ee6c8SWei Huang 	u32 blk_size, n_offset = 0;
179b74ee6c8SWei Huang 
180b74ee6c8SWei Huang 	while (size) {
181b74ee6c8SWei Huang 		blk_size = pmci_get_write_space(dev, size);
182b74ee6c8SWei Huang 		if (blk_size == 0) {
183b74ee6c8SWei Huang 			dev_err(pmci->dev, "get FIFO available size fail\n");
184b74ee6c8SWei Huang 			return -EIO;
185b74ee6c8SWei Huang 		}
186b74ee6c8SWei Huang 		size -= blk_size;
187b74ee6c8SWei Huang 		pmci_write_fifo(dev->mmio + PMCI_FLASH_FIFO, (char *)buf + n_offset,
188b74ee6c8SWei Huang 				blk_size);
189b74ee6c8SWei Huang 		n_offset += blk_size;
190b74ee6c8SWei Huang 	}
191b74ee6c8SWei Huang 
192b74ee6c8SWei Huang 	return 0;
193b74ee6c8SWei Huang }
194b74ee6c8SWei Huang 
195b74ee6c8SWei Huang static int
196b74ee6c8SWei Huang pmci_flash_bulk_write(struct intel_max10_device *dev, u32 addr,
197b74ee6c8SWei Huang 		void *buf, u32 size)
198b74ee6c8SWei Huang {
199b74ee6c8SWei Huang 	int ret;
200b74ee6c8SWei Huang 
201b74ee6c8SWei Huang 	pthread_mutex_lock(dev->bmc_ops.mutex);
202b74ee6c8SWei Huang 
203b74ee6c8SWei Huang 	ret = __pmci_flash_bulk_write(dev, addr, buf, size);
204b74ee6c8SWei Huang 
205b74ee6c8SWei Huang 	pthread_mutex_unlock(dev->bmc_ops.mutex);
206b74ee6c8SWei Huang 	return ret;
207b74ee6c8SWei Huang }
208b74ee6c8SWei Huang 
209b74ee6c8SWei Huang static int
210b74ee6c8SWei Huang pmci_set_flash_host_mux(struct intel_max10_device *dev, bool request)
211b74ee6c8SWei Huang {
212b74ee6c8SWei Huang 	u32 ctrl;
213b74ee6c8SWei Huang 	int ret;
214b74ee6c8SWei Huang 
215b74ee6c8SWei Huang 	ret = max10_sys_update_bits(dev,
216b74ee6c8SWei Huang 			m10bmc_base(dev) + M10BMC_PMCI_FLASH_CTRL,
217b74ee6c8SWei Huang 			FLASH_HOST_REQUEST,
218b74ee6c8SWei Huang 			SET_FIELD(FLASH_HOST_REQUEST, request));
219b74ee6c8SWei Huang 	if (ret)
220b74ee6c8SWei Huang 		return ret;
221b74ee6c8SWei Huang 
222b74ee6c8SWei Huang 	return opae_max10_read_poll_timeout(dev, m10bmc_base(dev) + M10BMC_PMCI_FLASH_CTRL,
223b74ee6c8SWei Huang 			ctrl, request ? (get_flash_mux(ctrl) == FLASH_MUX_HOST) :
224b74ee6c8SWei Huang 			(get_flash_mux(ctrl) != FLASH_MUX_HOST),
225b74ee6c8SWei Huang 			PMCI_FLASH_INT_US, PMCI_FLASH_TIMEOUT_US);
226b74ee6c8SWei Huang }
227b74ee6c8SWei Huang 
228b74ee6c8SWei Huang static int
229b74ee6c8SWei Huang pmci_get_mux(struct intel_max10_device *dev)
230b74ee6c8SWei Huang {
231b74ee6c8SWei Huang 	pthread_mutex_lock(dev->bmc_ops.mutex);
232b74ee6c8SWei Huang 	return pmci_set_flash_host_mux(dev, true);
233b74ee6c8SWei Huang }
234b74ee6c8SWei Huang 
235b74ee6c8SWei Huang static int
236b74ee6c8SWei Huang pmci_put_mux(struct intel_max10_device *dev)
237b74ee6c8SWei Huang {
238b74ee6c8SWei Huang 	int ret;
239b74ee6c8SWei Huang 
240b74ee6c8SWei Huang 	ret = pmci_set_flash_host_mux(dev, false);
241b74ee6c8SWei Huang 	pthread_mutex_unlock(dev->bmc_ops.mutex);
242b74ee6c8SWei Huang 	return ret;
243b74ee6c8SWei Huang }
244b74ee6c8SWei Huang 
245b74ee6c8SWei Huang static int
246b74ee6c8SWei Huang __pmci_flash_bulk_read(struct intel_max10_device *dev, u32 addr,
247b74ee6c8SWei Huang 		     void *buf, u32 size)
248b74ee6c8SWei Huang {
249b74ee6c8SWei Huang 	u32 blk_size, offset = 0, val;
250b74ee6c8SWei Huang 	int ret;
251b74ee6c8SWei Huang 
252b74ee6c8SWei Huang 	while (size) {
253b74ee6c8SWei Huang 		blk_size = min_t(u32, size, PMCI_READ_BLOCK_SIZE);
254b74ee6c8SWei Huang 
255b74ee6c8SWei Huang 		opae_writel(addr + offset, dev->mmio + PMCI_FLASH_ADDR);
256b74ee6c8SWei Huang 
257b74ee6c8SWei Huang 		opae_writel(SET_FIELD(PMCI_FLASH_READ_COUNT, blk_size / 4)
258b74ee6c8SWei Huang 				| PMCI_FLASH_RD_MODE,
259b74ee6c8SWei Huang 			dev->mmio + PMCI_FLASH_CTRL);
260b74ee6c8SWei Huang 
261b74ee6c8SWei Huang 		ret = opae_readl_poll_timeout((dev->mmio + PMCI_FLASH_CTRL),
262b74ee6c8SWei Huang 				val, !(val & PMCI_FLASH_BUSY),
263b74ee6c8SWei Huang 				PMCI_FLASH_INT_US,
264b74ee6c8SWei Huang 				PMCI_FLASH_TIMEOUT_US);
265b74ee6c8SWei Huang 		if (ret) {
266b74ee6c8SWei Huang 			dev_err(dev, "%s timed out on reading flash 0x%xn",
267b74ee6c8SWei Huang 				__func__, val);
268b74ee6c8SWei Huang 			return ret;
269b74ee6c8SWei Huang 		}
270b74ee6c8SWei Huang 
271b74ee6c8SWei Huang 		pmci_read_fifo(dev->mmio + PMCI_FLASH_FIFO, (char *)buf + offset,
272b74ee6c8SWei Huang 				blk_size);
273b74ee6c8SWei Huang 
274b74ee6c8SWei Huang 		size -= blk_size;
275b74ee6c8SWei Huang 		offset += blk_size;
276b74ee6c8SWei Huang 
277b74ee6c8SWei Huang 		opae_writel(0, dev->mmio + PMCI_FLASH_CTRL);
278b74ee6c8SWei Huang 	}
279b74ee6c8SWei Huang 
280b74ee6c8SWei Huang 	return 0;
281b74ee6c8SWei Huang }
282b74ee6c8SWei Huang 
283b74ee6c8SWei Huang static int
284b74ee6c8SWei Huang pmci_flash_bulk_read(struct intel_max10_device *dev, u32 addr,
285b74ee6c8SWei Huang 		     void *buf, u32 size)
286b74ee6c8SWei Huang {
287b74ee6c8SWei Huang 	int ret;
288b74ee6c8SWei Huang 
289b74ee6c8SWei Huang 	ret = pmci_get_mux(dev);
290b74ee6c8SWei Huang 	if (ret)
291b74ee6c8SWei Huang 		goto fail;
292b74ee6c8SWei Huang 
293b74ee6c8SWei Huang 	ret = __pmci_flash_bulk_read(dev, addr, buf, size);
294b74ee6c8SWei Huang 	if (ret)
295b74ee6c8SWei Huang 		goto fail;
296b74ee6c8SWei Huang 
297b74ee6c8SWei Huang 	return pmci_put_mux(dev);
298b74ee6c8SWei Huang 
299b74ee6c8SWei Huang fail:
300b74ee6c8SWei Huang 	pmci_put_mux(dev);
301b74ee6c8SWei Huang 	return ret;
302b74ee6c8SWei Huang }
303b74ee6c8SWei Huang 
304b74ee6c8SWei Huang static int pmci_check_flash_address(u32 start, u32 end)
305b74ee6c8SWei Huang {
306b74ee6c8SWei Huang 	if (start < PMCI_FLASH_START || end > PMCI_FLASH_END)
307b74ee6c8SWei Huang 		return -EINVAL;
308b74ee6c8SWei Huang 
309b74ee6c8SWei Huang 	return 0;
310b74ee6c8SWei Huang }
311b74ee6c8SWei Huang 
312b74ee6c8SWei Huang int opae_read_flash(struct intel_max10_device *dev, u32 addr,
313b74ee6c8SWei Huang 		u32 size, void *buf)
314b74ee6c8SWei Huang {
315b74ee6c8SWei Huang 	int ret;
316b74ee6c8SWei Huang 
317b74ee6c8SWei Huang 	if (!dev->bmc_ops.flash_read)
318b74ee6c8SWei Huang 		return -ENODEV;
319b74ee6c8SWei Huang 
320b74ee6c8SWei Huang 	if (!buf)
321b74ee6c8SWei Huang 		return -EINVAL;
322b74ee6c8SWei Huang 
323b74ee6c8SWei Huang 	if (dev->bmc_ops.check_flash_range) {
324b74ee6c8SWei Huang 		ret = dev->bmc_ops.check_flash_range(addr, addr + size);
325b74ee6c8SWei Huang 		if (ret)
326b74ee6c8SWei Huang 			return ret;
327b74ee6c8SWei Huang 	} else {
328b74ee6c8SWei Huang 		u32 top_addr = dev->staging_area_base + dev->staging_area_size;
329b74ee6c8SWei Huang 		if ((addr < dev->staging_area_base) ||
330b74ee6c8SWei Huang 			((addr + size) >= top_addr))
331b74ee6c8SWei Huang 			return -EINVAL;
332b74ee6c8SWei Huang 	}
333b74ee6c8SWei Huang 
334b74ee6c8SWei Huang 	ret = dev->bmc_ops.flash_read(dev, addr, buf, size);
335b74ee6c8SWei Huang 	if (ret)
336b74ee6c8SWei Huang 		return ret;
337b74ee6c8SWei Huang 
338b74ee6c8SWei Huang 	return 0;
339b74ee6c8SWei Huang }
340b74ee6c8SWei Huang 
341ca6eb0f7SWei Huang static int max10_spi_read(struct intel_max10_device *dev,
342ca6eb0f7SWei Huang 	unsigned int addr, unsigned int *val)
343ca6eb0f7SWei Huang {
344ca6eb0f7SWei Huang 	if (!dev)
345ca6eb0f7SWei Huang 		return -ENODEV;
346ca6eb0f7SWei Huang 
347ca6eb0f7SWei Huang 	dev_debug(dev, "%s: bus:0x%x, addr:0x%x\n", __func__, dev->bus, addr);
348ca6eb0f7SWei Huang 
349ca6eb0f7SWei Huang 	return spi_transaction_read(dev->spi_tran_dev,
350ca6eb0f7SWei Huang 			addr, 4, (unsigned char *)val);
351ca6eb0f7SWei Huang }
352ca6eb0f7SWei Huang 
353ca6eb0f7SWei Huang static int max10_spi_write(struct intel_max10_device *dev,
354ca6eb0f7SWei Huang 	unsigned int addr, unsigned int val)
355ca6eb0f7SWei Huang {
356ca6eb0f7SWei Huang 	unsigned int tmp = val;
357ca6eb0f7SWei Huang 
358ca6eb0f7SWei Huang 	if (!dev)
359ca6eb0f7SWei Huang 		return -ENODEV;
360ca6eb0f7SWei Huang 
361ca6eb0f7SWei Huang 	dev_debug(dev, "%s: bus:0x%x, reg:0x%x, val:0x%x\n", __func__,
362ca6eb0f7SWei Huang 			dev->bus, addr, val);
363ca6eb0f7SWei Huang 
364ca6eb0f7SWei Huang 	return spi_transaction_write(dev->spi_tran_dev,
365ca6eb0f7SWei Huang 			addr, 4, (unsigned char *)&tmp);
366ca6eb0f7SWei Huang }
367ca6eb0f7SWei Huang 
368ca6eb0f7SWei Huang static int indirect_bus_clr_cmd(struct intel_max10_device *dev)
369ca6eb0f7SWei Huang {
370ca6eb0f7SWei Huang 	unsigned int cmd;
371ca6eb0f7SWei Huang 	int ret;
372ca6eb0f7SWei Huang 
373ca6eb0f7SWei Huang 	opae_writel(0, dev->mmio + INDIRECT_CMD_OFF);
374ca6eb0f7SWei Huang 
375ca6eb0f7SWei Huang 	ret = opae_readl_poll_timeout((dev->mmio + INDIRECT_CMD_OFF), cmd,
376ca6eb0f7SWei Huang 				 (!cmd), INDIRECT_INT_US, INDIRECT_TIMEOUT_US);
377ca6eb0f7SWei Huang 
378ca6eb0f7SWei Huang 	if (ret)
379ca6eb0f7SWei Huang 		dev_err(dev, "%s timed out on clearing cmd 0x%x\n",
380ca6eb0f7SWei Huang 				__func__, cmd);
381ca6eb0f7SWei Huang 
382ca6eb0f7SWei Huang 	return ret;
383ca6eb0f7SWei Huang }
384ca6eb0f7SWei Huang 
385ca6eb0f7SWei Huang static int max10_indirect_reg_read(struct intel_max10_device *dev,
386ca6eb0f7SWei Huang 	unsigned int addr, unsigned int *val)
387ca6eb0f7SWei Huang {
388ca6eb0f7SWei Huang 	unsigned int cmd;
389ca6eb0f7SWei Huang 	int ret;
390ca6eb0f7SWei Huang 
391ca6eb0f7SWei Huang 	if (!dev)
392ca6eb0f7SWei Huang 		return -ENODEV;
393ca6eb0f7SWei Huang 
394ca6eb0f7SWei Huang 	pthread_mutex_lock(dev->bmc_ops.mutex);
395ca6eb0f7SWei Huang 
396ca6eb0f7SWei Huang 	cmd = opae_readl(dev->mmio + INDIRECT_CMD_OFF);
397ca6eb0f7SWei Huang 	if (cmd)
398ca6eb0f7SWei Huang 		dev_warn(dev, "%s non-zero cmd 0x%x\n", __func__, cmd);
399ca6eb0f7SWei Huang 
400ca6eb0f7SWei Huang 	opae_writel(addr, dev->mmio + INDIRECT_ADDR_OFF);
401ca6eb0f7SWei Huang 
402ca6eb0f7SWei Huang 	opae_writel(INDIRECT_CMD_RD, dev->mmio + INDIRECT_CMD_OFF);
403ca6eb0f7SWei Huang 
404ca6eb0f7SWei Huang 	ret = opae_readl_poll_timeout((dev->mmio + INDIRECT_CMD_OFF), cmd,
405ca6eb0f7SWei Huang 				 (cmd & INDIRECT_CMD_ACK), INDIRECT_INT_US,
406ca6eb0f7SWei Huang 				 INDIRECT_TIMEOUT_US);
407ca6eb0f7SWei Huang 
408ca6eb0f7SWei Huang 	*val = opae_readl(dev->mmio + INDIRECT_RD_OFF);
409ca6eb0f7SWei Huang 
410ca6eb0f7SWei Huang 	if (ret)
411ca6eb0f7SWei Huang 		dev_err(dev, "%s timed out on reg 0x%x cmd 0x%x\n",
412ca6eb0f7SWei Huang 				__func__, addr, cmd);
413ca6eb0f7SWei Huang 
414ca6eb0f7SWei Huang 	if (indirect_bus_clr_cmd(dev))
415ca6eb0f7SWei Huang 		ret = -ETIME;
416ca6eb0f7SWei Huang 
417ca6eb0f7SWei Huang 	pthread_mutex_unlock(dev->bmc_ops.mutex);
418ca6eb0f7SWei Huang 
419ca6eb0f7SWei Huang 	return ret;
420ca6eb0f7SWei Huang }
421ca6eb0f7SWei Huang 
422ca6eb0f7SWei Huang static int max10_indirect_reg_write(struct intel_max10_device *dev,
423ca6eb0f7SWei Huang 	unsigned int addr, unsigned int val)
424ca6eb0f7SWei Huang {
425ca6eb0f7SWei Huang 	unsigned int cmd;
426ca6eb0f7SWei Huang 	int ret;
427ca6eb0f7SWei Huang 
428ca6eb0f7SWei Huang 	if (!dev)
429ca6eb0f7SWei Huang 		return -ENODEV;
430ca6eb0f7SWei Huang 
431ca6eb0f7SWei Huang 	pthread_mutex_lock(dev->bmc_ops.mutex);
432ca6eb0f7SWei Huang 
433ca6eb0f7SWei Huang 	cmd = readl(dev->mmio + INDIRECT_CMD_OFF);
434ca6eb0f7SWei Huang 
435ca6eb0f7SWei Huang 	if (cmd)
436ca6eb0f7SWei Huang 		dev_warn(dev, "%s non-zero cmd 0x%x\n", __func__, cmd);
437ca6eb0f7SWei Huang 
438ca6eb0f7SWei Huang 	opae_writel(val, dev->mmio + INDIRECT_WR_OFF);
439ca6eb0f7SWei Huang 
440ca6eb0f7SWei Huang 	opae_writel(addr, dev->mmio + INDIRECT_ADDR_OFF);
441ca6eb0f7SWei Huang 
442ca6eb0f7SWei Huang 	writel(INDIRECT_CMD_WR, dev->mmio + INDIRECT_CMD_OFF);
443ca6eb0f7SWei Huang 
444ca6eb0f7SWei Huang 	ret = opae_readl_poll_timeout((dev->mmio + INDIRECT_CMD_OFF), cmd,
445ca6eb0f7SWei Huang 				 (cmd & INDIRECT_CMD_ACK), INDIRECT_INT_US,
446ca6eb0f7SWei Huang 				 INDIRECT_TIMEOUT_US);
447ca6eb0f7SWei Huang 
448ca6eb0f7SWei Huang 	if (ret)
449ca6eb0f7SWei Huang 		dev_err(dev, "%s timed out on reg 0x%x cmd 0x%x\n",
450ca6eb0f7SWei Huang 				__func__, addr, cmd);
451ca6eb0f7SWei Huang 
452ca6eb0f7SWei Huang 	if (indirect_bus_clr_cmd(dev))
453ca6eb0f7SWei Huang 		ret = -ETIME;
454ca6eb0f7SWei Huang 
455ca6eb0f7SWei Huang 	pthread_mutex_unlock(dev->bmc_ops.mutex);
456ca6eb0f7SWei Huang 
457ca6eb0f7SWei Huang 	return ret;
458ca6eb0f7SWei Huang }
459ca6eb0f7SWei Huang 
460ca6eb0f7SWei Huang const struct m10bmc_regmap m10bmc_pmci_regmap = {
461ca6eb0f7SWei Huang 	.reg_write = max10_indirect_reg_write,
462ca6eb0f7SWei Huang 	.reg_read = max10_indirect_reg_read,
463ca6eb0f7SWei Huang };
464ca6eb0f7SWei Huang 
465ca6eb0f7SWei Huang const struct m10bmc_regmap m10bmc_n3000_regmap = {
466ca6eb0f7SWei Huang 	.reg_write = max10_spi_write,
467ca6eb0f7SWei Huang 	.reg_read = max10_spi_read,
468ca6eb0f7SWei Huang };
469ca6eb0f7SWei Huang 
470e1defba4STianfei Zhang static struct max10_compatible_id max10_id_table[] = {
471e1defba4STianfei Zhang 	{.compatible = MAX10_PAC,},
472e1defba4STianfei Zhang 	{.compatible = MAX10_PAC_N3000,},
473e1defba4STianfei Zhang 	{.compatible = MAX10_PAC_END,}
474e1defba4STianfei Zhang };
475e1defba4STianfei Zhang 
476e1defba4STianfei Zhang static struct max10_compatible_id *max10_match_compatible(const char *fdt_root)
477e1defba4STianfei Zhang {
478e1defba4STianfei Zhang 	struct max10_compatible_id *id = max10_id_table;
479e1defba4STianfei Zhang 
480e1defba4STianfei Zhang 	for (; strcmp(id->compatible, MAX10_PAC_END); id++) {
481e1defba4STianfei Zhang 		if (fdt_node_check_compatible(fdt_root, 0, id->compatible))
482e1defba4STianfei Zhang 			continue;
483e1defba4STianfei Zhang 
484e1defba4STianfei Zhang 		return id;
485e1defba4STianfei Zhang 	}
486e1defba4STianfei Zhang 
487e1defba4STianfei Zhang 	return NULL;
488e1defba4STianfei Zhang }
489e1defba4STianfei Zhang 
490e1defba4STianfei Zhang static inline bool
491e1defba4STianfei Zhang is_max10_pac_n3000(struct intel_max10_device *max10)
492e1defba4STianfei Zhang {
493e1defba4STianfei Zhang 	return max10->id && !strcmp(max10->id->compatible,
494e1defba4STianfei Zhang 			MAX10_PAC_N3000);
495e1defba4STianfei Zhang }
496e1defba4STianfei Zhang 
497e1defba4STianfei Zhang static void max10_check_capability(struct intel_max10_device *max10)
498e1defba4STianfei Zhang {
499e1defba4STianfei Zhang 	if (!max10->fdt_root)
500e1defba4STianfei Zhang 		return;
501e1defba4STianfei Zhang 
502e1defba4STianfei Zhang 	if (is_max10_pac_n3000(max10)) {
503e1defba4STianfei Zhang 		max10->flags |= MAX10_FLAGS_NO_I2C2 |
504e1defba4STianfei Zhang 				MAX10_FLAGS_NO_BMCIMG_FLASH;
505e1defba4STianfei Zhang 		dev_info(max10, "found %s card\n", max10->id->compatible);
50671da60b8STianfei Zhang 	} else
50771da60b8STianfei Zhang 		max10->flags |= MAX10_FLAGS_MAC_CACHE;
508e1defba4STianfei Zhang }
509e1defba4STianfei Zhang 
5104a19f891STianfei Zhang static int altera_nor_flash_read(struct intel_max10_device *dev,
5114a19f891STianfei Zhang 	u32 offset, void *buffer, u32 len)
512e1defba4STianfei Zhang {
513e1defba4STianfei Zhang 	int word_len;
514e1defba4STianfei Zhang 	int i;
515e1defba4STianfei Zhang 	unsigned int *buf = (unsigned int *)buffer;
516e1defba4STianfei Zhang 	unsigned int value;
517e1defba4STianfei Zhang 	int ret;
518e1defba4STianfei Zhang 
5194a19f891STianfei Zhang 	if (!dev || !buffer || len <= 0)
520e1defba4STianfei Zhang 		return -ENODEV;
521e1defba4STianfei Zhang 
522e1defba4STianfei Zhang 	word_len = len/4;
523e1defba4STianfei Zhang 
524e1defba4STianfei Zhang 	for (i = 0; i < word_len; i++) {
5254a19f891STianfei Zhang 		ret = max10_reg_read(dev, offset + i*4,
526e1defba4STianfei Zhang 				&value);
527e1defba4STianfei Zhang 		if (ret)
528e1defba4STianfei Zhang 			return -EBUSY;
529e1defba4STianfei Zhang 
530e1defba4STianfei Zhang 		*buf++ = value;
531e1defba4STianfei Zhang 	}
532e1defba4STianfei Zhang 
533e1defba4STianfei Zhang 	return 0;
534e1defba4STianfei Zhang }
535e1defba4STianfei Zhang 
5364a19f891STianfei Zhang static int enable_nor_flash(struct intel_max10_device *dev, bool on)
537e1defba4STianfei Zhang {
538e1defba4STianfei Zhang 	unsigned int val = 0;
539e1defba4STianfei Zhang 	int ret;
540e1defba4STianfei Zhang 
5414a19f891STianfei Zhang 	ret = max10_sys_read(dev, RSU_REG, &val);
542e1defba4STianfei Zhang 	if (ret) {
543e1defba4STianfei Zhang 		dev_err(NULL "enabling flash error\n");
544e1defba4STianfei Zhang 		return ret;
545e1defba4STianfei Zhang 	}
546e1defba4STianfei Zhang 
547e1defba4STianfei Zhang 	if (on)
548e1defba4STianfei Zhang 		val |= RSU_ENABLE;
549e1defba4STianfei Zhang 	else
550e1defba4STianfei Zhang 		val &= ~RSU_ENABLE;
551e1defba4STianfei Zhang 
5524a19f891STianfei Zhang 	return max10_sys_write(dev, RSU_REG, val);
553e1defba4STianfei Zhang }
554e1defba4STianfei Zhang 
555e1defba4STianfei Zhang static int init_max10_device_table(struct intel_max10_device *max10)
556e1defba4STianfei Zhang {
557e41856b5SWei Huang 	struct altera_spi_device *spi = NULL;
558e1defba4STianfei Zhang 	struct max10_compatible_id *id;
559e1defba4STianfei Zhang 	struct fdt_header hdr;
560e1defba4STianfei Zhang 	char *fdt_root = NULL;
561e41856b5SWei Huang 	u32 dtb_magic = 0;
562e1defba4STianfei Zhang 	u32 dt_size, dt_addr, val;
563e41856b5SWei Huang 	int ret = 0;
564e1defba4STianfei Zhang 
565e41856b5SWei Huang 	spi = (struct altera_spi_device *)max10->spi_master;
566e41856b5SWei Huang 	if (!spi) {
567e41856b5SWei Huang 		dev_err(max10, "spi master is not set\n");
568e41856b5SWei Huang 		return -EINVAL;
569e41856b5SWei Huang 	}
570e41856b5SWei Huang 	if (spi->dtb)
571e41856b5SWei Huang 		dtb_magic = *(u32 *)spi->dtb;
572e41856b5SWei Huang 
573e41856b5SWei Huang 	if (dtb_magic != 0xEDFE0DD0) {
574e41856b5SWei Huang 		dev_info(max10, "read DTB from NOR flash\n");
5754a19f891STianfei Zhang 		ret = max10_sys_read(max10, DT_AVAIL_REG, &val);
576e1defba4STianfei Zhang 		if (ret) {
577e1defba4STianfei Zhang 			dev_err(max10 "cannot read DT_AVAIL_REG\n");
578e1defba4STianfei Zhang 			return ret;
579e1defba4STianfei Zhang 		}
580e1defba4STianfei Zhang 
581e1defba4STianfei Zhang 		if (!(val & DT_AVAIL)) {
582e1defba4STianfei Zhang 			dev_err(max10 "DT not available\n");
583e1defba4STianfei Zhang 			return -EINVAL;
584e1defba4STianfei Zhang 		}
585e1defba4STianfei Zhang 
5864a19f891STianfei Zhang 		ret = max10_sys_read(max10, DT_BASE_ADDR_REG, &dt_addr);
587e1defba4STianfei Zhang 		if (ret) {
588e1defba4STianfei Zhang 			dev_info(max10 "cannot get base addr of device table\n");
589e1defba4STianfei Zhang 			return ret;
590e1defba4STianfei Zhang 		}
591e1defba4STianfei Zhang 
5924a19f891STianfei Zhang 		ret = enable_nor_flash(max10, true);
593e1defba4STianfei Zhang 		if (ret) {
594e1defba4STianfei Zhang 			dev_err(max10 "fail to enable flash\n");
595e1defba4STianfei Zhang 			return ret;
596e1defba4STianfei Zhang 		}
597e1defba4STianfei Zhang 
5984a19f891STianfei Zhang 		ret = altera_nor_flash_read(max10, dt_addr, &hdr, sizeof(hdr));
599e1defba4STianfei Zhang 		if (ret) {
600e1defba4STianfei Zhang 			dev_err(max10 "read fdt header fail\n");
601e41856b5SWei Huang 			goto disable_nor_flash;
602e1defba4STianfei Zhang 		}
603e1defba4STianfei Zhang 
604e1defba4STianfei Zhang 		ret = fdt_check_header(&hdr);
605e1defba4STianfei Zhang 		if (ret) {
606e1defba4STianfei Zhang 			dev_err(max10 "check fdt header fail\n");
607e41856b5SWei Huang 			goto disable_nor_flash;
608e1defba4STianfei Zhang 		}
609e1defba4STianfei Zhang 
610e1defba4STianfei Zhang 		dt_size = fdt_totalsize(&hdr);
611e1defba4STianfei Zhang 		if (dt_size > DFT_MAX_SIZE) {
612e1defba4STianfei Zhang 			dev_err(max10 "invalid device table size\n");
613e1defba4STianfei Zhang 			ret = -EINVAL;
614e41856b5SWei Huang 			goto disable_nor_flash;
615e1defba4STianfei Zhang 		}
616e1defba4STianfei Zhang 
617e1defba4STianfei Zhang 		fdt_root = opae_malloc(dt_size);
618e1defba4STianfei Zhang 		if (!fdt_root) {
619e1defba4STianfei Zhang 			ret = -ENOMEM;
620e41856b5SWei Huang 			goto disable_nor_flash;
621e1defba4STianfei Zhang 		}
622e1defba4STianfei Zhang 
6234a19f891STianfei Zhang 		ret = altera_nor_flash_read(max10, dt_addr, fdt_root, dt_size);
624e1defba4STianfei Zhang 		if (ret) {
625e41856b5SWei Huang 			opae_free(fdt_root);
626e41856b5SWei Huang 			fdt_root = NULL;
627e1defba4STianfei Zhang 			dev_err(max10 "cannot read device table\n");
628e41856b5SWei Huang 			goto disable_nor_flash;
629e1defba4STianfei Zhang 		}
630e1defba4STianfei Zhang 
631e41856b5SWei Huang 		if (spi->dtb) {
632e41856b5SWei Huang 			if (*spi->dtb_sz_ptr < dt_size) {
633e41856b5SWei Huang 				dev_warn(max10,
634e41856b5SWei Huang 						 "share memory for dtb is smaller than required %u\n",
635e41856b5SWei Huang 						 dt_size);
636e41856b5SWei Huang 			} else {
637e41856b5SWei Huang 				*spi->dtb_sz_ptr = dt_size;
638e41856b5SWei Huang 			}
639e41856b5SWei Huang 			/* store dtb data into share memory  */
640e41856b5SWei Huang 			memcpy(spi->dtb, fdt_root, *spi->dtb_sz_ptr);
641e41856b5SWei Huang 		}
642e41856b5SWei Huang 
643e41856b5SWei Huang disable_nor_flash:
644e41856b5SWei Huang 		enable_nor_flash(max10, false);
645e41856b5SWei Huang 	} else {
646e41856b5SWei Huang 		if (*spi->dtb_sz_ptr > 0) {
647e41856b5SWei Huang 			dev_info(max10, "read DTB from shared memory\n");
648e41856b5SWei Huang 			fdt_root = opae_malloc(*spi->dtb_sz_ptr);
649e41856b5SWei Huang 			if (fdt_root)
650e41856b5SWei Huang 				memcpy(fdt_root, spi->dtb, *spi->dtb_sz_ptr);
651e41856b5SWei Huang 			else
652e41856b5SWei Huang 				ret = -ENOMEM;
653e41856b5SWei Huang 		}
654e41856b5SWei Huang 	}
655e41856b5SWei Huang 
656e41856b5SWei Huang 	if (fdt_root) {
657e1defba4STianfei Zhang 		id = max10_match_compatible(fdt_root);
658e1defba4STianfei Zhang 		if (!id) {
659e1defba4STianfei Zhang 			dev_err(max10 "max10 compatible not found\n");
660e1defba4STianfei Zhang 			ret = -ENODEV;
661e41856b5SWei Huang 		} else {
662e1defba4STianfei Zhang 			max10->flags |= MAX10_FLAGS_DEVICE_TABLE;
663e1defba4STianfei Zhang 			max10->id = id;
664e1defba4STianfei Zhang 			max10->fdt_root = fdt_root;
665e41856b5SWei Huang 		}
666e41856b5SWei Huang 	}
667e1defba4STianfei Zhang 
668e1defba4STianfei Zhang 	return ret;
669e1defba4STianfei Zhang }
670e1defba4STianfei Zhang 
67145f30172STianfei Zhang static u64 fdt_get_number(const fdt32_t *cell, int size)
67245f30172STianfei Zhang {
67345f30172STianfei Zhang 	u64 r = 0;
67445f30172STianfei Zhang 
67545f30172STianfei Zhang 	while (size--)
67645f30172STianfei Zhang 		r = (r << 32) | fdt32_to_cpu(*cell++);
67745f30172STianfei Zhang 
67845f30172STianfei Zhang 	return r;
67945f30172STianfei Zhang }
68045f30172STianfei Zhang 
68145f30172STianfei Zhang static int fdt_get_reg(const void *fdt, int node, unsigned int idx,
68245f30172STianfei Zhang 		u64 *start, u64 *size)
68345f30172STianfei Zhang {
68445f30172STianfei Zhang 	const fdt32_t *prop, *end;
68545f30172STianfei Zhang 	int na = 0, ns = 0, len = 0, parent;
68645f30172STianfei Zhang 
68745f30172STianfei Zhang 	parent = fdt_parent_offset(fdt, node);
68845f30172STianfei Zhang 	if (parent < 0)
68945f30172STianfei Zhang 		return parent;
69045f30172STianfei Zhang 
69145f30172STianfei Zhang 	prop = fdt_getprop(fdt, parent, "#address-cells", NULL);
69245f30172STianfei Zhang 	na = prop ? fdt32_to_cpu(*prop) : 2;
69345f30172STianfei Zhang 
69445f30172STianfei Zhang 	prop = fdt_getprop(fdt, parent, "#size-cells", NULL);
69545f30172STianfei Zhang 	ns = prop ? fdt32_to_cpu(*prop) : 2;
69645f30172STianfei Zhang 
69745f30172STianfei Zhang 	prop = fdt_getprop(fdt, node, "reg", &len);
69845f30172STianfei Zhang 	if (!prop)
69945f30172STianfei Zhang 		return -FDT_ERR_NOTFOUND;
70045f30172STianfei Zhang 
70145f30172STianfei Zhang 	end = prop + len/sizeof(*prop);
70245f30172STianfei Zhang 	prop = prop + (na + ns) * idx;
70345f30172STianfei Zhang 
70445f30172STianfei Zhang 	if (prop + na + ns > end)
70545f30172STianfei Zhang 		return -FDT_ERR_NOTFOUND;
70645f30172STianfei Zhang 
70745f30172STianfei Zhang 	*start = fdt_get_number(prop, na);
70845f30172STianfei Zhang 	*size = fdt_get_number(prop + na, ns);
70945f30172STianfei Zhang 
71045f30172STianfei Zhang 	return 0;
71145f30172STianfei Zhang }
71245f30172STianfei Zhang 
71345f30172STianfei Zhang static int __fdt_stringlist_search(const void *fdt, int offset,
71445f30172STianfei Zhang 		const char *prop, const char *string)
71545f30172STianfei Zhang {
71645f30172STianfei Zhang 	int length, len, index = 0;
71745f30172STianfei Zhang 	const char *list, *end;
71845f30172STianfei Zhang 
71945f30172STianfei Zhang 	list = fdt_getprop(fdt, offset, prop, &length);
72045f30172STianfei Zhang 	if (!list)
72145f30172STianfei Zhang 		return length;
72245f30172STianfei Zhang 
72345f30172STianfei Zhang 	len = strlen(string) + 1;
72445f30172STianfei Zhang 	end = list + length;
72545f30172STianfei Zhang 
72645f30172STianfei Zhang 	while (list < end) {
72745f30172STianfei Zhang 		length = strnlen(list, end - list) + 1;
72845f30172STianfei Zhang 
72945f30172STianfei Zhang 		if (list + length > end)
73045f30172STianfei Zhang 			return -FDT_ERR_BADVALUE;
73145f30172STianfei Zhang 
73245f30172STianfei Zhang 		if (length == len && memcmp(list, string, length) == 0)
73345f30172STianfei Zhang 			return index;
73445f30172STianfei Zhang 
73545f30172STianfei Zhang 		list += length;
73645f30172STianfei Zhang 		index++;
73745f30172STianfei Zhang 	}
73845f30172STianfei Zhang 
73945f30172STianfei Zhang 	return -FDT_ERR_NOTFOUND;
74045f30172STianfei Zhang }
74145f30172STianfei Zhang 
74245f30172STianfei Zhang static int fdt_get_named_reg(const void *fdt, int node, const char *name,
74345f30172STianfei Zhang 		u64 *start, u64 *size)
74445f30172STianfei Zhang {
74545f30172STianfei Zhang 	int idx;
74645f30172STianfei Zhang 
74745f30172STianfei Zhang 	idx = __fdt_stringlist_search(fdt, node, "reg-names", name);
74845f30172STianfei Zhang 	if (idx < 0)
74945f30172STianfei Zhang 		return idx;
75045f30172STianfei Zhang 
75145f30172STianfei Zhang 	return fdt_get_reg(fdt, node, idx, start, size);
75245f30172STianfei Zhang }
75345f30172STianfei Zhang 
7544a19f891STianfei Zhang static void max10_sensor_uinit(struct intel_max10_device *dev)
75545f30172STianfei Zhang {
75611986223SStephen Hemminger 	struct opae_sensor_info *info, *next;
75745f30172STianfei Zhang 
75811986223SStephen Hemminger 	TAILQ_FOREACH_SAFE(info, &dev->opae_sensor_list, node, next) {
7594a19f891STianfei Zhang 		TAILQ_REMOVE(&dev->opae_sensor_list, info, node);
76045f30172STianfei Zhang 		opae_free(info);
76145f30172STianfei Zhang 	}
76245f30172STianfei Zhang }
76345f30172STianfei Zhang 
76445f30172STianfei Zhang static bool sensor_reg_valid(struct sensor_reg *reg)
76545f30172STianfei Zhang {
76645f30172STianfei Zhang 	return !!reg->size;
76745f30172STianfei Zhang }
76845f30172STianfei Zhang 
7694a19f891STianfei Zhang static int max10_add_sensor(struct intel_max10_device *dev,
7704a19f891STianfei Zhang 	struct raw_sensor_info *info, struct opae_sensor_info *sensor)
77145f30172STianfei Zhang {
77245f30172STianfei Zhang 	int i;
77345f30172STianfei Zhang 	int ret = 0;
77445f30172STianfei Zhang 	unsigned int val;
77545f30172STianfei Zhang 
77645f30172STianfei Zhang 	if (!info || !sensor)
77745f30172STianfei Zhang 		return -ENODEV;
77845f30172STianfei Zhang 
77945f30172STianfei Zhang 	sensor->id = info->id;
78045f30172STianfei Zhang 	sensor->name = info->name;
78145f30172STianfei Zhang 	sensor->type = info->type;
78245f30172STianfei Zhang 	sensor->multiplier = info->multiplier;
78345f30172STianfei Zhang 
78445f30172STianfei Zhang 	for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++) {
78545f30172STianfei Zhang 		if (!sensor_reg_valid(&info->regs[i]))
78645f30172STianfei Zhang 			continue;
78745f30172STianfei Zhang 
7884a19f891STianfei Zhang 		ret = max10_sys_read(dev, info->regs[i].regoff, &val);
78945f30172STianfei Zhang 		if (ret)
79045f30172STianfei Zhang 			break;
79145f30172STianfei Zhang 
7924a19f891STianfei Zhang 		if (val == 0xdeadbeef) {
7934a19f891STianfei Zhang 			dev_debug(dev, "%s: sensor:%s invalid 0x%x at:%d\n",
7944a19f891STianfei Zhang 				__func__, sensor->name, val, i);
79545f30172STianfei Zhang 			continue;
7964a19f891STianfei Zhang 		}
79745f30172STianfei Zhang 
79845f30172STianfei Zhang 		val *= info->multiplier;
79945f30172STianfei Zhang 
80045f30172STianfei Zhang 		switch (i) {
80145f30172STianfei Zhang 		case SENSOR_REG_VALUE:
80245f30172STianfei Zhang 			sensor->value_reg = info->regs[i].regoff;
80345f30172STianfei Zhang 			sensor->flags |= OPAE_SENSOR_VALID;
80445f30172STianfei Zhang 			break;
80545f30172STianfei Zhang 		case SENSOR_REG_HIGH_WARN:
80645f30172STianfei Zhang 			sensor->high_warn = val;
80745f30172STianfei Zhang 			sensor->flags |= OPAE_SENSOR_HIGH_WARN_VALID;
80845f30172STianfei Zhang 			break;
80945f30172STianfei Zhang 		case SENSOR_REG_HIGH_FATAL:
81045f30172STianfei Zhang 			sensor->high_fatal = val;
81145f30172STianfei Zhang 			sensor->flags |= OPAE_SENSOR_HIGH_FATAL_VALID;
81245f30172STianfei Zhang 			break;
81345f30172STianfei Zhang 		case SENSOR_REG_LOW_WARN:
81445f30172STianfei Zhang 			sensor->low_warn = val;
81545f30172STianfei Zhang 			sensor->flags |= OPAE_SENSOR_LOW_WARN_VALID;
81645f30172STianfei Zhang 			break;
81745f30172STianfei Zhang 		case SENSOR_REG_LOW_FATAL:
81845f30172STianfei Zhang 			sensor->low_fatal = val;
81945f30172STianfei Zhang 			sensor->flags |= OPAE_SENSOR_LOW_FATAL_VALID;
82045f30172STianfei Zhang 			break;
82145f30172STianfei Zhang 		case SENSOR_REG_HYSTERESIS:
82245f30172STianfei Zhang 			sensor->hysteresis = val;
82345f30172STianfei Zhang 			sensor->flags |= OPAE_SENSOR_HYSTERESIS_VALID;
82445f30172STianfei Zhang 			break;
82545f30172STianfei Zhang 		}
82645f30172STianfei Zhang 	}
82745f30172STianfei Zhang 
82845f30172STianfei Zhang 	return ret;
82945f30172STianfei Zhang }
83045f30172STianfei Zhang 
83171da60b8STianfei Zhang static int
83271da60b8STianfei Zhang max10_sensor_init(struct intel_max10_device *dev, int parent)
83345f30172STianfei Zhang {
83445f30172STianfei Zhang 	int i, ret = 0, offset = 0;
83545f30172STianfei Zhang 	const fdt32_t *num;
83645f30172STianfei Zhang 	const char *ptr;
83745f30172STianfei Zhang 	u64 start, size;
83845f30172STianfei Zhang 	struct raw_sensor_info *raw;
83945f30172STianfei Zhang 	struct opae_sensor_info *sensor;
84045f30172STianfei Zhang 	char *fdt_root = dev->fdt_root;
84145f30172STianfei Zhang 
84245f30172STianfei Zhang 	if (!fdt_root) {
84345f30172STianfei Zhang 		dev_debug(dev, "skip sensor init as not find Device Tree\n");
84445f30172STianfei Zhang 		return 0;
84545f30172STianfei Zhang 	}
84645f30172STianfei Zhang 
84771da60b8STianfei Zhang 	fdt_for_each_subnode(offset, fdt_root, parent) {
84845f30172STianfei Zhang 		ptr = fdt_get_name(fdt_root, offset, NULL);
84945f30172STianfei Zhang 		if (!ptr) {
85045f30172STianfei Zhang 			dev_err(dev, "failed to fdt get name\n");
85145f30172STianfei Zhang 			continue;
85245f30172STianfei Zhang 		}
85345f30172STianfei Zhang 
85445f30172STianfei Zhang 		if (!strstr(ptr, "sensor")) {
85545f30172STianfei Zhang 			dev_debug(dev, "%s is not a sensor node\n", ptr);
85645f30172STianfei Zhang 			continue;
85745f30172STianfei Zhang 		}
85845f30172STianfei Zhang 
85945f30172STianfei Zhang 		dev_debug(dev, "found sensor node %s\n", ptr);
86045f30172STianfei Zhang 
86145f30172STianfei Zhang 		raw = (struct raw_sensor_info *)opae_zmalloc(sizeof(*raw));
86245f30172STianfei Zhang 		if (!raw) {
86345f30172STianfei Zhang 			ret = -ENOMEM;
86445f30172STianfei Zhang 			goto free_sensor;
86545f30172STianfei Zhang 		}
86645f30172STianfei Zhang 
86745f30172STianfei Zhang 		raw->name = fdt_getprop(fdt_root, offset, "sensor_name", NULL);
86845f30172STianfei Zhang 		if (!raw->name) {
86945f30172STianfei Zhang 			ret = -EINVAL;
87045f30172STianfei Zhang 			goto free_sensor;
87145f30172STianfei Zhang 		}
87245f30172STianfei Zhang 
87345f30172STianfei Zhang 		raw->type = fdt_getprop(fdt_root, offset, "type", NULL);
87445f30172STianfei Zhang 		if (!raw->type) {
87545f30172STianfei Zhang 			ret = -EINVAL;
87645f30172STianfei Zhang 			goto free_sensor;
87745f30172STianfei Zhang 		}
87845f30172STianfei Zhang 
87945f30172STianfei Zhang 		for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++) {
88045f30172STianfei Zhang 			ret = fdt_get_named_reg(fdt_root, offset,
88145f30172STianfei Zhang 					sensor_reg_name[i], &start,
88245f30172STianfei Zhang 					&size);
88345f30172STianfei Zhang 			if (ret) {
88445f30172STianfei Zhang 				dev_debug(dev, "no found %d: sensor node %s, %s\n",
88545f30172STianfei Zhang 						ret, ptr, sensor_reg_name[i]);
88645f30172STianfei Zhang 				if (i == SENSOR_REG_VALUE) {
88745f30172STianfei Zhang 					ret = -EINVAL;
88845f30172STianfei Zhang 					goto free_sensor;
88945f30172STianfei Zhang 				}
89045f30172STianfei Zhang 
89145f30172STianfei Zhang 				continue;
89245f30172STianfei Zhang 			}
89345f30172STianfei Zhang 
89471da60b8STianfei Zhang 			/* This is a hack to compatible with non-secure
89571da60b8STianfei Zhang 			 * solution. If sensors are included in root node,
89671da60b8STianfei Zhang 			 * then it's non-secure dtb, which use absolute addr
89771da60b8STianfei Zhang 			 * of non-secure solution.
89871da60b8STianfei Zhang 			 */
89971da60b8STianfei Zhang 			if (parent)
90045f30172STianfei Zhang 				raw->regs[i].regoff = start;
90171da60b8STianfei Zhang 			else
90271da60b8STianfei Zhang 				raw->regs[i].regoff = start -
90371da60b8STianfei Zhang 					MAX10_BASE_ADDR;
90445f30172STianfei Zhang 			raw->regs[i].size = size;
90545f30172STianfei Zhang 		}
90645f30172STianfei Zhang 
90745f30172STianfei Zhang 		num = fdt_getprop(fdt_root, offset, "id", NULL);
90845f30172STianfei Zhang 		if (!num) {
90945f30172STianfei Zhang 			ret = -EINVAL;
91045f30172STianfei Zhang 			goto free_sensor;
91145f30172STianfei Zhang 		}
91245f30172STianfei Zhang 
91345f30172STianfei Zhang 		raw->id = fdt32_to_cpu(*num);
91445f30172STianfei Zhang 		num = fdt_getprop(fdt_root, offset, "multiplier", NULL);
91545f30172STianfei Zhang 		raw->multiplier = num ? fdt32_to_cpu(*num) : 1;
91645f30172STianfei Zhang 
9174a19f891STianfei Zhang 		dev_debug(dev, "found sensor from DTB: %s: %s: %u: %u\n",
91845f30172STianfei Zhang 				raw->name, raw->type,
91945f30172STianfei Zhang 				raw->id, raw->multiplier);
92045f30172STianfei Zhang 
92145f30172STianfei Zhang 		for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++)
92245f30172STianfei Zhang 			dev_debug(dev, "sensor reg[%d]: %x: %zu\n",
92345f30172STianfei Zhang 					i, raw->regs[i].regoff,
92445f30172STianfei Zhang 					raw->regs[i].size);
92545f30172STianfei Zhang 
92645f30172STianfei Zhang 		sensor = opae_zmalloc(sizeof(*sensor));
92745f30172STianfei Zhang 		if (!sensor) {
92845f30172STianfei Zhang 			ret = -EINVAL;
92945f30172STianfei Zhang 			goto free_sensor;
93045f30172STianfei Zhang 		}
93145f30172STianfei Zhang 
9324a19f891STianfei Zhang 		if (max10_add_sensor(dev, raw, sensor)) {
93345f30172STianfei Zhang 			ret = -EINVAL;
93445f30172STianfei Zhang 			opae_free(sensor);
93545f30172STianfei Zhang 			goto free_sensor;
93645f30172STianfei Zhang 		}
93745f30172STianfei Zhang 
9384a19f891STianfei Zhang 		if (sensor->flags & OPAE_SENSOR_VALID) {
9394a19f891STianfei Zhang 			TAILQ_INSERT_TAIL(&dev->opae_sensor_list, sensor, node);
9404a19f891STianfei Zhang 			dev_info(dev, "found valid sensor: %s\n", sensor->name);
9414a19f891STianfei Zhang 		} else
94245f30172STianfei Zhang 			opae_free(sensor);
94345f30172STianfei Zhang 
94445f30172STianfei Zhang 		opae_free(raw);
94545f30172STianfei Zhang 	}
94645f30172STianfei Zhang 
94745f30172STianfei Zhang 	return 0;
94845f30172STianfei Zhang 
94945f30172STianfei Zhang free_sensor:
95045f30172STianfei Zhang 	if (raw)
95145f30172STianfei Zhang 		opae_free(raw);
9524a19f891STianfei Zhang 	max10_sensor_uinit(dev);
95345f30172STianfei Zhang 	return ret;
95445f30172STianfei Zhang }
95545f30172STianfei Zhang 
95671da60b8STianfei Zhang static int check_max10_version(struct intel_max10_device *dev)
95771da60b8STianfei Zhang {
95871da60b8STianfei Zhang 	unsigned int v;
95971da60b8STianfei Zhang 
9604a19f891STianfei Zhang 	if (!max10_reg_read(dev, MAX10_SEC_BASE_ADDR + MAX10_BUILD_VER,
96171da60b8STianfei Zhang 				&v)) {
96271da60b8STianfei Zhang 		if (v != 0xffffffff) {
96371da60b8STianfei Zhang 			dev_info(dev, "secure MAX10 detected\n");
96471da60b8STianfei Zhang 			dev->flags |= MAX10_FLAGS_SECURE;
96571da60b8STianfei Zhang 		} else {
96671da60b8STianfei Zhang 			dev_info(dev, "non-secure MAX10 detected\n");
96771da60b8STianfei Zhang 		}
96871da60b8STianfei Zhang 		return 0;
96971da60b8STianfei Zhang 	}
97071da60b8STianfei Zhang 
97171da60b8STianfei Zhang 	return -ENODEV;
97271da60b8STianfei Zhang }
97371da60b8STianfei Zhang 
974a05bd1b4SWei Huang static int max10_staging_area_init(struct intel_max10_device *dev)
975a05bd1b4SWei Huang {
976a05bd1b4SWei Huang 	char *fdt_root = dev->fdt_root;
977a05bd1b4SWei Huang 	int ret, offset = 0;
978a05bd1b4SWei Huang 	u64 start, size;
979a05bd1b4SWei Huang 
980a05bd1b4SWei Huang 	if (!fdt_root) {
981a05bd1b4SWei Huang 		dev_debug(dev,
982a05bd1b4SWei Huang 			"skip staging area init as not find Device Tree\n");
983a05bd1b4SWei Huang 		return -ENODEV;
984a05bd1b4SWei Huang 	}
985a05bd1b4SWei Huang 
986a05bd1b4SWei Huang 	dev->staging_area_size = 0;
987a05bd1b4SWei Huang 
988a05bd1b4SWei Huang 	fdt_for_each_subnode(offset, fdt_root, 0) {
989a05bd1b4SWei Huang 		if (fdt_node_check_compatible(fdt_root, offset,
990a05bd1b4SWei Huang 					      "ifpga-sec-mgr,staging-area"))
991a05bd1b4SWei Huang 			continue;
992a05bd1b4SWei Huang 
993a05bd1b4SWei Huang 		ret = fdt_get_reg(fdt_root, offset, 0, &start, &size);
99492a3b62bSWei Huang 		if (ret)
99592a3b62bSWei Huang 			return ret;
99692a3b62bSWei Huang 
99792a3b62bSWei Huang 		if ((start & 0x3) || (start > MAX_STAGING_AREA_BASE) ||
99892a3b62bSWei Huang 			(size > MAX_STAGING_AREA_SIZE))
99992a3b62bSWei Huang 			return -EINVAL;
100092a3b62bSWei Huang 
1001a05bd1b4SWei Huang 		dev->staging_area_base = start;
1002a05bd1b4SWei Huang 		dev->staging_area_size = size;
100392a3b62bSWei Huang 
1004a05bd1b4SWei Huang 		return ret;
1005a05bd1b4SWei Huang 	}
1006a05bd1b4SWei Huang 
1007a05bd1b4SWei Huang 	return -ENODEV;
1008a05bd1b4SWei Huang }
1009a05bd1b4SWei Huang 
101071da60b8STianfei Zhang static int
101171da60b8STianfei Zhang max10_secure_hw_init(struct intel_max10_device *dev)
101271da60b8STianfei Zhang {
101371da60b8STianfei Zhang 	int offset, sysmgr_offset = 0;
101471da60b8STianfei Zhang 	char *fdt_root;
101571da60b8STianfei Zhang 
101671da60b8STianfei Zhang 	fdt_root = dev->fdt_root;
101771da60b8STianfei Zhang 	if (!fdt_root) {
101871da60b8STianfei Zhang 		dev_debug(dev, "skip init as not find Device Tree\n");
101971da60b8STianfei Zhang 		return 0;
102071da60b8STianfei Zhang 	}
102171da60b8STianfei Zhang 
102271da60b8STianfei Zhang 	fdt_for_each_subnode(offset, fdt_root, 0) {
102371da60b8STianfei Zhang 		if (!fdt_node_check_compatible(fdt_root, offset,
102471da60b8STianfei Zhang 					"intel-max10,system-manager")) {
102571da60b8STianfei Zhang 			sysmgr_offset = offset;
102671da60b8STianfei Zhang 			break;
102771da60b8STianfei Zhang 		}
102871da60b8STianfei Zhang 	}
102971da60b8STianfei Zhang 
103071da60b8STianfei Zhang 	max10_check_capability(dev);
103171da60b8STianfei Zhang 
103271da60b8STianfei Zhang 	max10_sensor_init(dev, sysmgr_offset);
103371da60b8STianfei Zhang 
1034a05bd1b4SWei Huang 	max10_staging_area_init(dev);
1035a05bd1b4SWei Huang 
103671da60b8STianfei Zhang 	return 0;
103771da60b8STianfei Zhang }
103871da60b8STianfei Zhang 
103971da60b8STianfei Zhang static int
104071da60b8STianfei Zhang max10_non_secure_hw_init(struct intel_max10_device *dev)
104171da60b8STianfei Zhang {
104271da60b8STianfei Zhang 	max10_check_capability(dev);
104371da60b8STianfei Zhang 
104471da60b8STianfei Zhang 	max10_sensor_init(dev, 0);
104571da60b8STianfei Zhang 
104671da60b8STianfei Zhang 	return 0;
104771da60b8STianfei Zhang }
104871da60b8STianfei Zhang 
10497c4fe2adSWei Huang int max10_get_fpga_load_info(struct intel_max10_device *dev, unsigned int *val)
10507c4fe2adSWei Huang {
10517c4fe2adSWei Huang 	int ret;
10527c4fe2adSWei Huang 	unsigned int value;
10537c4fe2adSWei Huang 
10547c4fe2adSWei Huang 	/* read FPGA loading information */
10557c4fe2adSWei Huang 	ret = max10_sys_read(dev, dev->csr->fpga_page_info, &value);
10567c4fe2adSWei Huang 	if (ret) {
10577c4fe2adSWei Huang 		dev_err(dev, "fail to get FPGA loading info\n");
10587c4fe2adSWei Huang 		return ret;
10597c4fe2adSWei Huang 	}
10607c4fe2adSWei Huang 
10617c4fe2adSWei Huang 	if (dev->type == M10_N3000)
10627c4fe2adSWei Huang 		*val = value & 0x7;
10637c4fe2adSWei Huang 	else if (dev->type == M10_N6000) {
10647c4fe2adSWei Huang 		if (!GET_FIELD(PMCI_FPGA_CONFIGURED, value))
10657c4fe2adSWei Huang 			return -EINVAL;
10667c4fe2adSWei Huang 		*val = GET_FIELD(PMCI_FPGA_BOOT_PAGE, value);
10677c4fe2adSWei Huang 	}
10687c4fe2adSWei Huang 
10697c4fe2adSWei Huang 	return 0;
10707c4fe2adSWei Huang }
10717c4fe2adSWei Huang 
10727c4fe2adSWei Huang int max10_get_bmc_version(struct intel_max10_device *dev, unsigned int *val)
10737c4fe2adSWei Huang {
10747c4fe2adSWei Huang 	int ret;
10757c4fe2adSWei Huang 
10767c4fe2adSWei Huang 	ret = max10_sys_read(dev, dev->csr->build_version, val);
10777c4fe2adSWei Huang 	if (ret)
10787c4fe2adSWei Huang 		return ret;
10797c4fe2adSWei Huang 
10807c4fe2adSWei Huang 	return 0;
10817c4fe2adSWei Huang }
10827c4fe2adSWei Huang 
10837c4fe2adSWei Huang int max10_get_bmcfw_version(struct intel_max10_device *dev, unsigned int *val)
10847c4fe2adSWei Huang {
10857c4fe2adSWei Huang 	int ret;
10867c4fe2adSWei Huang 
10877c4fe2adSWei Huang 	ret = max10_sys_read(dev, dev->csr->fw_version, val);
10887c4fe2adSWei Huang 	if (ret)
10897c4fe2adSWei Huang 		return ret;
10907c4fe2adSWei Huang 
10917c4fe2adSWei Huang 	return 0;
10927c4fe2adSWei Huang }
10937c4fe2adSWei Huang 
1094ca6eb0f7SWei Huang static const struct m10bmc_csr m10bmc_spi_csr = {
1095ca6eb0f7SWei Huang 	.base = MAX10_SEC_BASE_ADDR,
1096ca6eb0f7SWei Huang 	.build_version = MAX10_BUILD_VER,
1097ca6eb0f7SWei Huang 	.fw_version = NIOS2_FW_VERSION,
1098ca6eb0f7SWei Huang 	.fpga_page_info = FPGA_PAGE_INFO,
1099ca6eb0f7SWei Huang 	.doorbell = MAX10_DOORBELL,
1100ca6eb0f7SWei Huang 	.auth_result = MAX10_AUTH_RESULT,
1101ca6eb0f7SWei Huang };
1102473c88f9SBruce Richardson 
1103ca6eb0f7SWei Huang static const struct m10bmc_csr m10bmc_pmci_csr = {
1104ca6eb0f7SWei Huang 	.base = M10BMC_PMCI_SYS_BASE,
1105ca6eb0f7SWei Huang 	.build_version = M10BMC_PMCI_BUILD_VER,
1106ca6eb0f7SWei Huang 	.fw_version = NIOS2_PMCI_FW_VERSION,
1107ca6eb0f7SWei Huang 	.fpga_page_info = M10BMC_PMCI_FPGA_CONF_STS,
1108ca6eb0f7SWei Huang 	.doorbell = M10BMC_PMCI_DOORBELL,
1109ca6eb0f7SWei Huang 	.auth_result = M10BMC_PMCI_AUTH_RESULT,
1110ca6eb0f7SWei Huang };
1111ca6eb0f7SWei Huang 
1112528a9fc2SWei Huang static const struct max10_sensor_raw_data n6000bmc_temp_tbl[] = {
1113528a9fc2SWei Huang 	{ 0x444, 0x448, 0x44c, 0x0, 0x0, 500,
1114528a9fc2SWei Huang 		"FPGA E-TILE Temperature #1" },
1115528a9fc2SWei Huang 	{ 0x450, 0x454, 0x458, 0x0, 0x0, 500,
1116528a9fc2SWei Huang 		"FPGA E-TILE Temperature #2" },
1117528a9fc2SWei Huang 	{ 0x45c, 0x460, 0x464, 0x0, 0x0, 500,
1118528a9fc2SWei Huang 		"FPGA E-TILE Temperature #3" },
1119528a9fc2SWei Huang 	{ 0x468, 0x46c, 0x470, 0x0, 0x0, 500,
1120528a9fc2SWei Huang 		"FPGA E-TILE Temperature #4" },
1121528a9fc2SWei Huang 	{ 0x474, 0x478, 0x47c, 0x0, 0x0, 500,
1122528a9fc2SWei Huang 		"FPGA P-TILE Temperature" },
1123528a9fc2SWei Huang 	{ 0x484, 0x488, 0x48c, 0x0, 0x0, 500,
1124528a9fc2SWei Huang 		"FPGA FABRIC Digital Temperature#1" },
1125528a9fc2SWei Huang 	{ 0x490, 0x494, 0x498, 0x0, 0x0, 500,
1126528a9fc2SWei Huang 		"FPGA FABRIC Digital Temperature#2" },
1127528a9fc2SWei Huang 	{ 0x49c, 0x4a0, 0x4a4, 0x0, 0x0, 500,
1128528a9fc2SWei Huang 		"FPGA FABRIC Digital Temperature#3" },
1129528a9fc2SWei Huang 	{ 0x4a8, 0x4ac, 0x4b0, 0x0, 0x0, 500,
1130528a9fc2SWei Huang 		"FPGA FABRIC Digital Temperature#4" },
1131528a9fc2SWei Huang 	{ 0x4b4, 0x4b8, 0x4bc, 0x0, 0x0, 500,
1132528a9fc2SWei Huang 		"FPGA FABRIC Digital Temperature#5" },
1133528a9fc2SWei Huang 	{ 0x4c0, 0x4c4, 0x4c8, 0x0, 0x0, 500,
1134528a9fc2SWei Huang 		"FPGA FABRIC Remote Digital Temperature#1" },
1135528a9fc2SWei Huang 	{ 0x4cc, 0x4d0, 0x4d4, 0x0, 0x0, 500,
1136528a9fc2SWei Huang 		"FPGA FABRIC Remote Digital Temperature#2" },
1137528a9fc2SWei Huang 	{ 0x4d8, 0x4dc, 0x4e0, 0x0, 0x0, 500,
1138528a9fc2SWei Huang 		"FPGA FABRIC Remote Digital Temperature#3" },
1139528a9fc2SWei Huang 	{ 0x4e4, 0x4e8, 0x4ec, 0x0, 0x0, 500,
1140528a9fc2SWei Huang 		"FPGA FABRIC Remote Digital Temperature#4" },
1141528a9fc2SWei Huang 	{ 0x4f0, 0x4f4, 0x4f8, 0x0, 0x0, 500,
1142528a9fc2SWei Huang 		"Board Top Near FPGA Temperature" },
1143528a9fc2SWei Huang 	{ 0x4fc, 0x500, 0x504, 0x52c, 0x0, 500,
1144528a9fc2SWei Huang 		"Board Bottom Near CVL Temperature" },
1145528a9fc2SWei Huang 	{ 0x508, 0x50c, 0x510, 0x52c, 0x0, 500,
1146528a9fc2SWei Huang 		"Board Top East Near VRs Temperature" },
1147528a9fc2SWei Huang 	{ 0x514, 0x518, 0x51c, 0x52c, 0x0, 500,
1148528a9fc2SWei Huang 		"Columbiaville Die Temperature" },
1149528a9fc2SWei Huang 	{ 0x520, 0x524, 0x528, 0x52c, 0x0, 500,
1150528a9fc2SWei Huang 		"Board Rear Side Temperature" },
1151528a9fc2SWei Huang 	{ 0x530, 0x534, 0x538, 0x52c, 0x0, 500,
1152528a9fc2SWei Huang 		"Board Front Side Temperature" },
1153528a9fc2SWei Huang 	{ 0x53c, 0x540, 0x544, 0x0, 0x0, 500,
1154528a9fc2SWei Huang 		"QSFP1 Temperature" },
1155528a9fc2SWei Huang 	{ 0x548, 0x54c, 0x550, 0x0, 0x0, 500,
1156528a9fc2SWei Huang 		"QSFP2 Temperature" },
1157528a9fc2SWei Huang 	{ 0x554, 0x0, 0x0, 0x0, 0x0, 500,
1158528a9fc2SWei Huang 		"FPGA Core Voltage Phase 0 VR Temperature" },
1159528a9fc2SWei Huang 	{ 0x560, 0x0, 0x0, 0x0, 0x0, 500,
1160528a9fc2SWei Huang 		"FPGA Core Voltage Phase 1 VR Temperature" },
1161528a9fc2SWei Huang 	{ 0x56c, 0x0, 0x0, 0x0, 0x0, 500,
1162528a9fc2SWei Huang 		"FPGA Core Voltage Phase 2 VR Temperature" },
1163528a9fc2SWei Huang 	{ 0x578, 0x0, 0x0, 0x0, 0x0, 500,
1164528a9fc2SWei Huang 		"FPGA Core Voltage VR Controller Temperature" },
1165528a9fc2SWei Huang 	{ 0x584, 0x0, 0x0, 0x0, 0x0, 500,
1166528a9fc2SWei Huang 		"FPGA VCCH VR Temperature" },
1167528a9fc2SWei Huang 	{ 0x590, 0x0, 0x0, 0x0, 0x0, 500,
1168528a9fc2SWei Huang 		"FPGA VCC_1V2 VR Temperature" },
1169528a9fc2SWei Huang 	{ 0x59c, 0x0, 0x0, 0x0, 0x0, 500,
1170528a9fc2SWei Huang 		"FPGA VCCH, VCC_1V2 VR Controller Temperature" },
1171528a9fc2SWei Huang 	{ 0x5a8, 0x0, 0x0, 0x0, 0x0, 500,
1172528a9fc2SWei Huang 		"3V3 VR Temperature" },
1173528a9fc2SWei Huang 	{ 0x5b4, 0x5b8, 0x5bc, 0x0, 0x0, 500,
1174528a9fc2SWei Huang 		"CVL Core Voltage VR Temperature" },
1175528a9fc2SWei Huang 	{ 0x5c4, 0x5c8, 0x5cc, 0x5c0, 0x0, 500,
1176528a9fc2SWei Huang 		"FPGA P-Tile Temperature [Remote]" },
1177528a9fc2SWei Huang 	{ 0x5d0, 0x5d4, 0x5d8, 0x5c0, 0x0, 500,
1178528a9fc2SWei Huang 		"FPGA E-Tile Temperature [Remote]" },
1179528a9fc2SWei Huang 	{ 0x5dc, 0x5e0, 0x5e4, 0x5c0, 0x0, 500,
1180528a9fc2SWei Huang 		"FPGA SDM Temperature [Remote]" },
1181528a9fc2SWei Huang 	{ 0x5e8, 0x5ec, 0x5f0, 0x5c0, 0x0, 500,
1182528a9fc2SWei Huang 		"FPGA Corner Temperature [Remote]" },
1183528a9fc2SWei Huang };
1184528a9fc2SWei Huang 
1185528a9fc2SWei Huang static const struct max10_sensor_data n6000bmc_tmp_data = {
1186528a9fc2SWei Huang 	.type = SENSOR_TMP_NAME,
1187528a9fc2SWei Huang 	.number = ARRAY_SIZE(n6000bmc_temp_tbl),
1188528a9fc2SWei Huang 	.table = n6000bmc_temp_tbl,
1189528a9fc2SWei Huang };
1190528a9fc2SWei Huang 
1191528a9fc2SWei Huang static const struct max10_sensor_raw_data n6000bmc_in_tbl[] = {
1192528a9fc2SWei Huang 	{ 0x5f4, 0x0, 0x0, 0x0, 0x0, 1,
1193528a9fc2SWei Huang 		"Inlet 12V PCIe Rail Voltage" },
1194528a9fc2SWei Huang 	{ 0x60c, 0x0, 0x0, 0x0, 0x0, 1,
1195528a9fc2SWei Huang 		"Inlet 12V Aux Rail Voltage" },
1196528a9fc2SWei Huang 	{ 0x624, 0x0, 0x0, 0x0, 0x0, 1,
1197528a9fc2SWei Huang 		"Inlet 3V3 PCIe Rail Voltage" },
1198528a9fc2SWei Huang 	{ 0x63c, 0x0, 0x0, 0x0, 0x0, 1,
1199528a9fc2SWei Huang 		"FPGA Core Voltage Rail Voltage" },
1200528a9fc2SWei Huang 	{ 0x644, 0x0, 0x0, 0x0, 0x0, 1,
1201528a9fc2SWei Huang 		"FPGA VCCH Rail Voltage" },
1202528a9fc2SWei Huang 	{ 0x64c, 0x0, 0x0, 0x0, 0x0, 1,
1203528a9fc2SWei Huang 		"FPGA VCC_1V2 Rail Voltage" },
1204528a9fc2SWei Huang 	{ 0x654, 0x0, 0x0, 0x0, 0x0, 1,
1205528a9fc2SWei Huang 		"FPGA VCCH_GXER_1V1, VCCA_1V8 Voltage" },
1206528a9fc2SWei Huang 	{ 0x664, 0x0, 0x0, 0x0, 0x0, 1,
1207528a9fc2SWei Huang 		"FPGA VCCIO_1V2 Voltage" },
1208528a9fc2SWei Huang 	{ 0x674, 0x0, 0x0, 0x0, 0x0, 1,
1209528a9fc2SWei Huang 		"CVL Non Core Rails Inlet Voltage" },
1210528a9fc2SWei Huang 	{ 0x684, 0x0, 0x0, 0x0, 0x0, 1,
1211528a9fc2SWei Huang 		"MAX10 & Board CLK PWR 3V3 Inlet Voltage" },
1212528a9fc2SWei Huang 	{ 0x694, 0x0, 0x0, 0x0, 0x0, 1,
1213528a9fc2SWei Huang 		"CVL Core Voltage Rail Voltage" },
1214528a9fc2SWei Huang 	{ 0x6ac, 0x0, 0x0, 0x0, 0x0, 1,
1215528a9fc2SWei Huang 		"Board 3V3 VR Voltage" },
1216528a9fc2SWei Huang 	{ 0x6b4, 0x0, 0x0, 0x0, 0x0, 1,
1217528a9fc2SWei Huang 		"QSFP 3V3 Rail Voltage" },
1218528a9fc2SWei Huang 	{ 0x6c4, 0x0, 0x0, 0x0, 0x0, 1,
1219528a9fc2SWei Huang 		"QSFP (Primary) Supply Rail Voltage" },
1220528a9fc2SWei Huang 	{ 0x6c8, 0x0, 0x0, 0x0, 0x0, 1,
1221528a9fc2SWei Huang 		"QSFP (Secondary) Supply Rail Voltage" },
1222528a9fc2SWei Huang 	{ 0x6cc, 0x0, 0x0, 0x0, 0x0, 1,
1223528a9fc2SWei Huang 		"VCCCLK_GXER_2V5 Voltage" },
1224528a9fc2SWei Huang 	{ 0x6d0, 0x0, 0x0, 0x0, 0x0, 1,
1225528a9fc2SWei Huang 		"AVDDH_1V1_CVL Voltage" },
1226528a9fc2SWei Huang 	{ 0x6d4, 0x0, 0x0, 0x0, 0x0, 1,
1227528a9fc2SWei Huang 		"VDDH_1V8_CVL Voltage" },
1228528a9fc2SWei Huang 	{ 0x6d8, 0x0, 0x0, 0x0, 0x0, 1,
1229528a9fc2SWei Huang 		"VCCA_PLL Voltage" },
1230528a9fc2SWei Huang 	{ 0x6e0, 0x0, 0x0, 0x0, 0x0, 1,
1231528a9fc2SWei Huang 		"VCCRT_GXER_0V9 Voltage" },
1232528a9fc2SWei Huang 	{ 0x6e8, 0x0, 0x0, 0x0, 0x0, 1,
1233528a9fc2SWei Huang 		"VCCRT_GXEL_0V9 Voltage" },
1234528a9fc2SWei Huang 	{ 0x6f0, 0x0, 0x0, 0x0, 0x0, 1,
1235528a9fc2SWei Huang 		"VCCH_GXPL_1V8 Voltage" },
1236528a9fc2SWei Huang 	{ 0x6f4, 0x0, 0x0, 0x0, 0x0, 1,
1237528a9fc2SWei Huang 		"VCCPT_1V8 Voltage" },
1238528a9fc2SWei Huang 	{ 0x6fc, 0x0, 0x0, 0x0, 0x0, 1,
1239528a9fc2SWei Huang 		"VCC_3V3_M10 Voltage" },
1240528a9fc2SWei Huang 	{ 0x700, 0x0, 0x0, 0x0, 0x0, 1,
1241528a9fc2SWei Huang 		"VCC_1V8_M10 Voltage" },
1242528a9fc2SWei Huang 	{ 0x704, 0x0, 0x0, 0x0, 0x0, 1,
1243528a9fc2SWei Huang 		"VCC_1V2_EMIF1_2_3 Voltage" },
1244528a9fc2SWei Huang 	{ 0x70c, 0x0, 0x0, 0x0, 0x0, 1,
1245528a9fc2SWei Huang 		"VCC_1V2_EMIF4_5 Voltage" },
1246528a9fc2SWei Huang 	{ 0x714, 0x0, 0x0, 0x0, 0x0, 1,
1247528a9fc2SWei Huang 		"VCCA_1V8 Voltage" },
1248528a9fc2SWei Huang 	{ 0x718, 0x0, 0x0, 0x0, 0x0, 1,
1249528a9fc2SWei Huang 		"VCCH_GXER_1V1 Voltage" },
1250528a9fc2SWei Huang 	{ 0x71c, 0x0, 0x0, 0x0, 0x0, 1,
1251528a9fc2SWei Huang 		"AVDD_ETH_0V9_CVL Voltage" },
1252528a9fc2SWei Huang 	{ 0x720, 0x0, 0x0, 0x0, 0x0, 1,
1253528a9fc2SWei Huang 		"AVDD_PCIE_0V9_CVL Voltage" },
1254528a9fc2SWei Huang };
1255528a9fc2SWei Huang 
1256528a9fc2SWei Huang static const struct max10_sensor_data n6000bmc_in_data = {
1257528a9fc2SWei Huang 	.type = SENSOR_IN_NAME,
1258528a9fc2SWei Huang 	.number = ARRAY_SIZE(n6000bmc_in_tbl),
1259528a9fc2SWei Huang 	.table = n6000bmc_in_tbl,
1260528a9fc2SWei Huang };
1261528a9fc2SWei Huang 
1262528a9fc2SWei Huang static const struct max10_sensor_raw_data n6000bmc_curr_tbl[] = {
1263528a9fc2SWei Huang 	{ 0x600, 0x604, 0x608, 0x0, 0x0, 1,
1264528a9fc2SWei Huang 		"Inlet 12V PCIe Rail Current" },
1265528a9fc2SWei Huang 	{ 0x618, 0x61c, 0x620, 0x0, 0x0, 1,
1266528a9fc2SWei Huang 		"Inlet 12V Aux Rail Current" },
1267528a9fc2SWei Huang 	{ 0x630, 0x634, 0x638, 0x0, 0x0, 1,
1268528a9fc2SWei Huang 		"Inlet 3V3 PCIe Rail Current" },
1269528a9fc2SWei Huang 	{ 0x640, 0x0, 0x0, 0x0, 0x0, 1,
1270528a9fc2SWei Huang 		"FPGA Core Voltage Rail Current" },
1271528a9fc2SWei Huang 	{ 0x648, 0x0, 0x0, 0x0, 0x0, 1,
1272528a9fc2SWei Huang 		"FPGA VCCH Rail Current" },
1273528a9fc2SWei Huang 	{ 0x650, 0x0, 0x0, 0x0, 0x0, 1,
1274528a9fc2SWei Huang 		"FPGA VCC_1V2 Rail Current" },
1275528a9fc2SWei Huang 	{ 0x658, 0x65c, 0x660, 0x0, 0x0, 1,
1276528a9fc2SWei Huang 		"FPGA VCCH_GXER_1V1, VCCA_1V8 Current" },
1277528a9fc2SWei Huang 	{ 0x668, 0x66c, 0x670, 0x0, 0x0, 1,
1278528a9fc2SWei Huang 		"FPGA VCCIO_1V2 Current" },
1279528a9fc2SWei Huang 	{ 0x678, 0x67c, 0x680, 0x0, 0x0, 1,
1280528a9fc2SWei Huang 		"CVL Non Core Rails Inlet Current" },
1281528a9fc2SWei Huang 	{ 0x688, 0x68c, 0x680, 0x0, 0x0, 1,
1282528a9fc2SWei Huang 		"MAX10 & Board CLK PWR 3V3 Inlet Current" },
1283528a9fc2SWei Huang 	{ 0x690, 0x0, 0x0, 0x0, 0x0, 1,
1284528a9fc2SWei Huang 		"CVL Core Voltage Rail Current" },
1285528a9fc2SWei Huang 	{ 0x6b0, 0x0, 0x0, 0x0, 0x0, 1,
1286528a9fc2SWei Huang 		"Board 3V3 VR Current" },
1287528a9fc2SWei Huang 	{ 0x6b8, 0x6bc, 0x670, 0x0, 0x0, 1,
1288528a9fc2SWei Huang 		"QSFP 3V3 Rail Current" },
1289528a9fc2SWei Huang };
1290528a9fc2SWei Huang 
1291528a9fc2SWei Huang static const struct max10_sensor_data n6000bmc_curr_data = {
1292528a9fc2SWei Huang 	.type = SENSOR_CURR_NAME,
1293528a9fc2SWei Huang 	.number = ARRAY_SIZE(n6000bmc_curr_tbl),
1294528a9fc2SWei Huang 	.table = n6000bmc_curr_tbl,
1295528a9fc2SWei Huang };
1296528a9fc2SWei Huang 
1297528a9fc2SWei Huang static const struct max10_sensor_raw_data n6000bmc_power_tbl[] = {
1298528a9fc2SWei Huang 	{ 0x724, 0x0, 0x0, 0x0, 0x0, 1000, "Board Power" },
1299528a9fc2SWei Huang };
1300528a9fc2SWei Huang 
1301528a9fc2SWei Huang static const struct max10_sensor_data n6000bmc_power_data = {
1302528a9fc2SWei Huang 	.type = SENSOR_POWER_NAME,
1303528a9fc2SWei Huang 	.number = ARRAY_SIZE(n6000bmc_power_tbl),
1304528a9fc2SWei Huang 	.table = n6000bmc_power_tbl,
1305528a9fc2SWei Huang };
1306528a9fc2SWei Huang 
1307528a9fc2SWei Huang static const struct max10_sensor_board_data n6000bmc_sensor_board_data = {
1308528a9fc2SWei Huang 	.tables = {
1309528a9fc2SWei Huang 		[sensor_temp] = &n6000bmc_tmp_data,
1310528a9fc2SWei Huang 		[sensor_in] = &n6000bmc_in_data,
1311528a9fc2SWei Huang 		[sensor_curr] = &n6000bmc_curr_data,
1312528a9fc2SWei Huang 		[sensor_power] = &n6000bmc_power_data,
1313528a9fc2SWei Huang 	},
1314528a9fc2SWei Huang };
1315528a9fc2SWei Huang 
1316528a9fc2SWei Huang static int get_sensor_data(struct intel_max10_device *dev,
1317528a9fc2SWei Huang 		struct opae_sensor_info *sensor,
1318528a9fc2SWei Huang 		unsigned int *value,
1319528a9fc2SWei Huang 		unsigned int reg,
1320528a9fc2SWei Huang 		unsigned int flags)
1321528a9fc2SWei Huang {
1322528a9fc2SWei Huang 	int ret;
1323528a9fc2SWei Huang 	unsigned int data;
1324528a9fc2SWei Huang 
1325528a9fc2SWei Huang 	if (!reg)
1326528a9fc2SWei Huang 		return 0;
1327528a9fc2SWei Huang 
1328528a9fc2SWei Huang 	ret = max10_sys_read(dev, reg, &data);
1329528a9fc2SWei Huang 	if (ret)
1330528a9fc2SWei Huang 		return ret;
1331528a9fc2SWei Huang 
1332528a9fc2SWei Huang 	if (data == SENSOR_INVALID) {
1333528a9fc2SWei Huang 		dev_debug(dev, "%s: sensor:%s invalid 0x%x at:%d\n",
1334528a9fc2SWei Huang 				__func__, sensor->name, data, reg);
1335528a9fc2SWei Huang 		return ret;
1336528a9fc2SWei Huang 	}
1337528a9fc2SWei Huang 
1338528a9fc2SWei Huang 	*value = data * sensor->multiplier;
1339528a9fc2SWei Huang 	sensor->flags |= flags;
1340528a9fc2SWei Huang 
1341528a9fc2SWei Huang 	return 0;
1342528a9fc2SWei Huang }
1343528a9fc2SWei Huang 
1344528a9fc2SWei Huang static int max10_parse_sensor_data(struct intel_max10_device *dev,
1345528a9fc2SWei Huang 		const struct max10_sensor_data *sdata)
1346528a9fc2SWei Huang {
1347528a9fc2SWei Huang 	struct opae_sensor_info *sensor;
1348528a9fc2SWei Huang 	const struct max10_sensor_raw_data *raw;
1349528a9fc2SWei Huang 	const struct max10_sensor_raw_data *table =
1350528a9fc2SWei Huang 		(const struct max10_sensor_raw_data *)sdata->table;
1351528a9fc2SWei Huang 	unsigned int i;
1352528a9fc2SWei Huang 	static unsigned int sensor_id;
1353528a9fc2SWei Huang 	int ret = 0;
1354528a9fc2SWei Huang 
1355528a9fc2SWei Huang 	for (i = 0; i < sdata->number; i++) {
1356528a9fc2SWei Huang 		raw = &table[i];
1357528a9fc2SWei Huang 
1358528a9fc2SWei Huang 		sensor = opae_zmalloc(sizeof(*sensor));
1359528a9fc2SWei Huang 		if (!sensor) {
1360528a9fc2SWei Huang 			ret = -EINVAL;
1361528a9fc2SWei Huang 			goto free_sensor;
1362528a9fc2SWei Huang 		}
1363528a9fc2SWei Huang 
1364528a9fc2SWei Huang 		sensor->type = sdata->type;
1365528a9fc2SWei Huang 		sensor->id = sensor_id++;
1366528a9fc2SWei Huang 
1367528a9fc2SWei Huang 		if (!raw->reg_input)
1368528a9fc2SWei Huang 			continue;
1369528a9fc2SWei Huang 
1370528a9fc2SWei Huang 		sensor->value_reg = raw->reg_input;
1371528a9fc2SWei Huang 		sensor->multiplier = raw->multiplier;
1372528a9fc2SWei Huang 		sensor->name = raw->label;
1373528a9fc2SWei Huang 
1374528a9fc2SWei Huang 		ret = get_sensor_data(dev, sensor,
1375528a9fc2SWei Huang 				&sensor->high_warn,
1376528a9fc2SWei Huang 				raw->reg_high_warn,
1377528a9fc2SWei Huang 				OPAE_SENSOR_HIGH_WARN_VALID);
1378528a9fc2SWei Huang 		if (ret)
1379528a9fc2SWei Huang 			break;
1380528a9fc2SWei Huang 
1381528a9fc2SWei Huang 		ret = get_sensor_data(dev, sensor,
1382528a9fc2SWei Huang 				&sensor->high_fatal,
1383528a9fc2SWei Huang 				raw->reg_high_fatal,
1384528a9fc2SWei Huang 				OPAE_SENSOR_HIGH_FATAL_VALID);
1385528a9fc2SWei Huang 		if (ret)
1386528a9fc2SWei Huang 			break;
1387528a9fc2SWei Huang 
1388528a9fc2SWei Huang 		ret = get_sensor_data(dev, sensor,
1389528a9fc2SWei Huang 				&sensor->hysteresis,
1390528a9fc2SWei Huang 				raw->reg_hyst,
1391528a9fc2SWei Huang 				OPAE_SENSOR_HYSTERESIS_VALID);
1392528a9fc2SWei Huang 		if (ret)
1393528a9fc2SWei Huang 			break;
1394528a9fc2SWei Huang 
1395528a9fc2SWei Huang 		ret = get_sensor_data(dev, sensor,
1396528a9fc2SWei Huang 				&sensor->low_warn,
1397528a9fc2SWei Huang 				raw->reg_low_warn,
1398528a9fc2SWei Huang 				OPAE_SENSOR_LOW_WARN_VALID);
1399528a9fc2SWei Huang 		if (ret)
1400528a9fc2SWei Huang 			break;
1401528a9fc2SWei Huang 
1402528a9fc2SWei Huang 		sensor->flags |= OPAE_SENSOR_VALID;
1403528a9fc2SWei Huang 
1404528a9fc2SWei Huang 		TAILQ_INSERT_TAIL(&dev->opae_sensor_list, sensor, node);
1405528a9fc2SWei Huang 		dev_info(dev, "found valid sensor: %s\n", sensor->name);
1406528a9fc2SWei Huang 	}
1407528a9fc2SWei Huang 
1408528a9fc2SWei Huang 	return ret;
1409528a9fc2SWei Huang 
1410528a9fc2SWei Huang free_sensor:
1411528a9fc2SWei Huang 	max10_sensor_uinit(dev);
1412528a9fc2SWei Huang 	return ret;
1413528a9fc2SWei Huang }
1414528a9fc2SWei Huang 
1415528a9fc2SWei Huang static int max10_sensor_init_table(struct intel_max10_device *dev,
1416528a9fc2SWei Huang 		const struct max10_sensor_board_data *data)
1417528a9fc2SWei Huang {
1418528a9fc2SWei Huang 	int ret = 0;
1419528a9fc2SWei Huang 	unsigned int i;
1420528a9fc2SWei Huang 	const struct max10_sensor_data *sdata;
1421528a9fc2SWei Huang 
1422528a9fc2SWei Huang 	for (i = 0; i < ARRAY_SIZE(data->tables); i++) {
1423528a9fc2SWei Huang 		sdata = data->tables[i];
1424528a9fc2SWei Huang 		if (!sdata)
1425528a9fc2SWei Huang 			continue;
1426528a9fc2SWei Huang 		ret = max10_parse_sensor_data(dev, sdata);
1427528a9fc2SWei Huang 		if (ret)
1428528a9fc2SWei Huang 			break;
1429528a9fc2SWei Huang 	}
1430528a9fc2SWei Huang 
1431528a9fc2SWei Huang 	return ret;
1432528a9fc2SWei Huang }
1433528a9fc2SWei Huang 
1434ca6eb0f7SWei Huang int
1435ca6eb0f7SWei Huang intel_max10_device_init(struct intel_max10_device *dev)
1436ca6eb0f7SWei Huang {
1437ca6eb0f7SWei Huang 	int ret = 0;
1438473c88f9SBruce Richardson 
14394a19f891STianfei Zhang 	TAILQ_INIT(&dev->opae_sensor_list);
14404a19f891STianfei Zhang 
1441473c88f9SBruce Richardson 
1442ca6eb0f7SWei Huang 	if (dev->type == M10_N3000) {
1443ca6eb0f7SWei Huang 		dev->ops = &m10bmc_n3000_regmap;
1444ca6eb0f7SWei Huang 		dev->csr = &m10bmc_spi_csr;
1445473c88f9SBruce Richardson 
1446b74ee6c8SWei Huang 		dev->raw_blk_ops.write_blk = n3000_bulk_raw_write;
1447b74ee6c8SWei Huang 		dev->raw_blk_ops.read_blk = n3000_bulk_raw_read;
1448b74ee6c8SWei Huang 		dev->bmc_ops.flash_read = n3000_flash_read;
1449b74ee6c8SWei Huang 		dev->bmc_ops.flash_write = n3000_flash_write;
1450b74ee6c8SWei Huang 
145171da60b8STianfei Zhang 		/* check the max10 version */
145271da60b8STianfei Zhang 		ret = check_max10_version(dev);
1453e1defba4STianfei Zhang 		if (ret) {
145471da60b8STianfei Zhang 			dev_err(dev, "Failed to find max10 hardware!\n");
1455ca6eb0f7SWei Huang 			return ret;
1456e1defba4STianfei Zhang 		}
1457e1defba4STianfei Zhang 
145871da60b8STianfei Zhang 		/* load the MAX10 device table */
145971da60b8STianfei Zhang 		ret = init_max10_device_table(dev);
146071da60b8STianfei Zhang 		if (ret) {
146171da60b8STianfei Zhang 			dev_err(dev, "Init max10 device table fail\n");
1462ca6eb0f7SWei Huang 			return ret;
146371da60b8STianfei Zhang 		}
146471da60b8STianfei Zhang 
146571da60b8STianfei Zhang 		/* init max10 devices, like sensor*/
146671da60b8STianfei Zhang 		if (dev->flags & MAX10_FLAGS_SECURE)
146771da60b8STianfei Zhang 			ret = max10_secure_hw_init(dev);
146871da60b8STianfei Zhang 		else
146971da60b8STianfei Zhang 			ret = max10_non_secure_hw_init(dev);
147071da60b8STianfei Zhang 		if (ret) {
147171da60b8STianfei Zhang 			dev_err(dev, "Failed to init max10 hardware!\n");
1472e1defba4STianfei Zhang 			opae_free(dev->fdt_root);
1473ca6eb0f7SWei Huang 			return ret;
1474ca6eb0f7SWei Huang 		}
1475ca6eb0f7SWei Huang 	} else if (dev->type == M10_N6000) {
1476ca6eb0f7SWei Huang 		dev->ops = &m10bmc_pmci_regmap;
1477ca6eb0f7SWei Huang 		dev->csr = &m10bmc_pmci_csr;
1478ca6eb0f7SWei Huang 		dev->staging_area_size = MAX_STAGING_AREA_SIZE;
1479ca6eb0f7SWei Huang 		dev->flags |= MAX10_FLAGS_SECURE;
1480473c88f9SBruce Richardson 
1481b74ee6c8SWei Huang 		dev->bmc_ops.flash_read = pmci_flash_bulk_read;
1482b74ee6c8SWei Huang 		dev->bmc_ops.flash_write = pmci_flash_bulk_write;
1483b74ee6c8SWei Huang 		dev->bmc_ops.check_flash_range = pmci_check_flash_address;
1484b74ee6c8SWei Huang 
1485528a9fc2SWei Huang 		ret = max10_sensor_init_table(dev, &n6000bmc_sensor_board_data);
1486528a9fc2SWei Huang 		if (ret)
1487528a9fc2SWei Huang 			return ret;
1488528a9fc2SWei Huang 
1489*d28809c2SAriel Otilibili 		pthread_mutex_init(&dev->bmc_ops.lock, NULL);
1490ca6eb0f7SWei Huang 		if (!dev->bmc_ops.mutex)
1491ca6eb0f7SWei Huang 			dev->bmc_ops.mutex = &dev->bmc_ops.lock;
1492ca6eb0f7SWei Huang 	}
1493ca6eb0f7SWei Huang 
1494ca6eb0f7SWei Huang 	return ret;
1495473c88f9SBruce Richardson }
1496473c88f9SBruce Richardson 
1497473c88f9SBruce Richardson int intel_max10_device_remove(struct intel_max10_device *dev)
1498473c88f9SBruce Richardson {
1499473c88f9SBruce Richardson 	if (!dev)
1500473c88f9SBruce Richardson 		return 0;
1501473c88f9SBruce Richardson 
1502ca6eb0f7SWei Huang 	pthread_mutex_destroy(&dev->bmc_ops.lock);
150345f30172STianfei Zhang 
1504ca6eb0f7SWei Huang 	if (dev->type == M10_N3000) {
1505ca6eb0f7SWei Huang 		max10_sensor_uinit(dev);
1506473c88f9SBruce Richardson 
1507e1defba4STianfei Zhang 		if (dev->fdt_root)
1508e1defba4STianfei Zhang 			opae_free(dev->fdt_root);
1509ca6eb0f7SWei Huang 	}
1510473c88f9SBruce Richardson 
1511473c88f9SBruce Richardson 	return 0;
1512473c88f9SBruce Richardson }
1513