1 /*
2  * Copyright (c) 2022 Intel Corporation
3  *
4  * Intel I/O Controller Hub (ICH) later renamed to Intel Platform Controller
5  * Hub (PCH) SMBus driver.
6  *
7  * PCH provides SMBus 2.0 - compliant Host Controller.
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #include <zephyr/types.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/device.h>
15 
16 #include <zephyr/drivers/smbus.h>
17 #include <zephyr/drivers/pcie/pcie.h>
18 
19 #define DT_DRV_COMPAT intel_pch_smbus
20 
21 #include <zephyr/logging/log.h>
22 LOG_MODULE_REGISTER(intel_pch, CONFIG_SMBUS_LOG_LEVEL);
23 
24 #include "smbus_utils.h"
25 #include "intel_pch_smbus.h"
26 
27 /**
28  * @note Following notions are used:
29  *  * periph_addr - Peripheral address (Slave address mentioned in the Specs)
30  *  * command - First byte to send in the SMBus protocol operations except for
31  *              Quick and Byte Read. Also known as register.
32  */
33 
34 /**
35  * Intel PCH configuration acquired from DTS during device initialization
36  */
37 struct pch_config {
38 	/* IRQ configuration function */
39 	void (*config_func)(const struct device *dev);
40 	struct pcie_dev *pcie;
41 };
42 
43 /**
44  * Intel PCH internal driver data
45  */
46 struct pch_data {
47 	DEVICE_MMIO_RAM;
48 	io_port_t sba;
49 	uint32_t config;
50 	uint8_t status;
51 
52 	struct k_mutex mutex;
53 	struct k_sem completion_sync;
54 	const struct device *dev;
55 
56 #if defined(CONFIG_SMBUS_INTEL_PCH_SMBALERT)
57 	/* smbalert callback list */
58 	sys_slist_t smbalert_cbs;
59 	/* smbalert work */
60 	struct k_work smb_alert_work;
61 #endif /* CONFIG_SMBUS_INTEL_PCH_SMBALERT */
62 
63 #if defined(CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY)
64 	/* Host Notify callback list */
65 	sys_slist_t host_notify_cbs;
66 	/* Host Notify work */
67 	struct k_work host_notify_work;
68 	/* Host Notify peripheral device address */
69 	uint8_t notify_addr;
70 	/* Host Notify data received */
71 	uint16_t notify_data;
72 #endif /* CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY */
73 };
74 
75 /**
76  * Helpers for accessing Intel PCH SMBus registers. Depending on
77  * configuration option MMIO or IO method will be used.
78  */
79 #if defined(CONFIG_SMBUS_INTEL_PCH_ACCESS_MMIO)
pch_reg_read(const struct device * dev,uint8_t reg)80 static uint8_t pch_reg_read(const struct device *dev, uint8_t reg)
81 {
82 	return sys_read8(DEVICE_MMIO_GET(dev) + reg);
83 }
84 
pch_reg_write(const struct device * dev,uint8_t reg,uint8_t val)85 static void pch_reg_write(const struct device *dev, uint8_t reg, uint8_t val)
86 {
87 	sys_write8(val, DEVICE_MMIO_GET(dev) + reg);
88 }
89 #elif defined(CONFIG_SMBUS_INTEL_PCH_ACCESS_IO)
pch_reg_read(const struct device * dev,uint8_t reg)90 static uint8_t pch_reg_read(const struct device *dev, uint8_t reg)
91 {
92 	struct pch_data *data = dev->data;
93 
94 	return sys_in8(data->sba + reg);
95 }
96 
pch_reg_write(const struct device * dev,uint8_t reg,uint8_t val)97 static void pch_reg_write(const struct device *dev, uint8_t reg, uint8_t val)
98 {
99 	struct pch_data *data = dev->data;
100 
101 	sys_out8(val, data->sba + reg);
102 }
103 #else
104 #error Wrong PCH Register Access Mode
105 #endif
106 
107 #if defined(CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY)
host_notify_work(struct k_work * work)108 static void host_notify_work(struct k_work *work)
109 {
110 	struct pch_data *data = CONTAINER_OF(work, struct pch_data,
111 					     host_notify_work);
112 	const struct device *dev = data->dev;
113 	uint8_t addr = data->notify_addr;
114 
115 	smbus_fire_callbacks(&data->host_notify_cbs, dev, addr);
116 }
117 
pch_smbus_host_notify_set_cb(const struct device * dev,struct smbus_callback * cb)118 static int pch_smbus_host_notify_set_cb(const struct device *dev,
119 					struct smbus_callback *cb)
120 {
121 	struct pch_data *data = dev->data;
122 
123 	LOG_DBG("dev %p cb %p", dev, cb);
124 
125 	return smbus_callback_set(&data->host_notify_cbs, cb);
126 }
127 
pch_smbus_host_notify_remove_cb(const struct device * dev,struct smbus_callback * cb)128 static int pch_smbus_host_notify_remove_cb(const struct device *dev,
129 					   struct smbus_callback *cb)
130 {
131 	struct pch_data *data = dev->data;
132 
133 	LOG_DBG("dev %p cb %p", dev, cb);
134 
135 	return smbus_callback_remove(&data->host_notify_cbs, cb);
136 }
137 #endif /* CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY */
138 
139 #if defined(CONFIG_SMBUS_INTEL_PCH_SMBALERT)
smbalert_work(struct k_work * work)140 static void smbalert_work(struct k_work *work)
141 {
142 	struct pch_data *data = CONTAINER_OF(work, struct pch_data,
143 					     smb_alert_work);
144 	const struct device *dev = data->dev;
145 
146 	smbus_loop_alert_devices(dev, &data->smbalert_cbs);
147 }
148 
pch_smbus_smbalert_set_sb(const struct device * dev,struct smbus_callback * cb)149 static int pch_smbus_smbalert_set_sb(const struct device *dev,
150 				     struct smbus_callback *cb)
151 {
152 	struct pch_data *data = dev->data;
153 
154 	LOG_DBG("dev %p cb %p", dev, cb);
155 
156 	return smbus_callback_set(&data->smbalert_cbs, cb);
157 }
158 
pch_smbus_smbalert_remove_sb(const struct device * dev,struct smbus_callback * cb)159 static int pch_smbus_smbalert_remove_sb(const struct device *dev,
160 					struct smbus_callback *cb)
161 {
162 	struct pch_data *data = dev->data;
163 
164 	LOG_DBG("dev %p cb %p", dev, cb);
165 
166 	return smbus_callback_remove(&data->smbalert_cbs, cb);
167 }
168 #endif /* CONFIG_SMBUS_INTEL_PCH_SMBALERT */
169 
pch_configure(const struct device * dev,uint32_t config)170 static int pch_configure(const struct device *dev, uint32_t config)
171 {
172 	struct pch_data *data = dev->data;
173 
174 	LOG_DBG("dev %p config 0x%x", dev, config);
175 
176 	if (config & SMBUS_MODE_HOST_NOTIFY) {
177 		uint8_t status;
178 
179 		if (!IS_ENABLED(CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY)) {
180 			LOG_ERR("Error configuring Host Notify");
181 			return -EINVAL;
182 		}
183 
184 		/* Enable Host Notify interrupts */
185 		status = pch_reg_read(dev, PCH_SMBUS_SCMD);
186 		status |= PCH_SMBUS_SCMD_HNI_EN;
187 		pch_reg_write(dev, PCH_SMBUS_SCMD, status);
188 	}
189 
190 	if (config & SMBUS_MODE_SMBALERT) {
191 		uint8_t status;
192 
193 		if (!IS_ENABLED(CONFIG_SMBUS_INTEL_PCH_SMBALERT)) {
194 			LOG_ERR("Error configuring SMBALERT");
195 			return -EINVAL;
196 		}
197 
198 		/* Disable SMBALERT_DIS */
199 		status = pch_reg_read(dev, PCH_SMBUS_SCMD);
200 		status &= ~PCH_SMBUS_SCMD_SMBALERT_DIS;
201 		pch_reg_write(dev, PCH_SMBUS_SCMD, status);
202 	}
203 
204 	/* Keep config for a moment */
205 	data->config = config;
206 
207 	return 0;
208 }
209 
pch_get_config(const struct device * dev,uint32_t * config)210 static int pch_get_config(const struct device *dev, uint32_t *config)
211 {
212 	struct pch_data *data = dev->data;
213 
214 	*config = data->config;
215 
216 	return 0;
217 }
218 
219 /* Device initialization function */
pch_smbus_init(const struct device * dev)220 static int pch_smbus_init(const struct device *dev)
221 {
222 	const struct pch_config * const config = dev->config;
223 	struct pch_data *data = dev->data;
224 	struct pcie_bar mbar;
225 	uint32_t val;
226 
227 	if (config->pcie->bdf == PCIE_BDF_NONE) {
228 		LOG_ERR("Cannot probe PCI device");
229 		return -ENODEV;
230 	}
231 
232 	val = pcie_conf_read(config->pcie->bdf, PCIE_CONF_CMDSTAT);
233 	if (val & PCIE_CONF_CMDSTAT_INTERRUPT) {
234 		LOG_WRN("Pending interrupt, continuing");
235 	}
236 
237 	if (IS_ENABLED(CONFIG_SMBUS_INTEL_PCH_ACCESS_MMIO)) {
238 		pcie_probe_mbar(config->pcie->bdf, 0, &mbar);
239 		pcie_set_cmd(config->pcie->bdf, PCIE_CONF_CMDSTAT_MEM, true);
240 
241 		device_map(DEVICE_MMIO_RAM_PTR(dev), mbar.phys_addr, mbar.size,
242 			   K_MEM_CACHE_NONE);
243 
244 		LOG_DBG("Mapped 0x%lx size 0x%lx to 0x%lx",
245 			mbar.phys_addr, mbar.size, DEVICE_MMIO_GET(dev));
246 	} else {
247 		pcie_set_cmd(config->pcie->bdf, PCIE_CONF_CMDSTAT_IO, true);
248 		val = pcie_conf_read(config->pcie->bdf, PCIE_CONF_BAR4);
249 		if (!PCIE_CONF_BAR_IO(val)) {
250 			LOG_ERR("Cannot read IO BAR");
251 			return -EINVAL;
252 		}
253 
254 		data->sba = PCIE_CONF_BAR_ADDR(val);
255 
256 		LOG_DBG("Using I/O address 0x%x", data->sba);
257 	}
258 
259 	val = pcie_conf_read(config->pcie->bdf, PCH_SMBUS_HCFG);
260 	if ((val & PCH_SMBUS_HCFG_HST_EN) == 0) {
261 		LOG_ERR("SMBus Host Controller is disabled");
262 		return -EINVAL;
263 	}
264 
265 	/* Initialize mutex and semaphore */
266 	k_mutex_init(&data->mutex);
267 	k_sem_init(&data->completion_sync, 0, 1);
268 
269 	data->dev = dev;
270 
271 	/* Initialize work structures */
272 
273 #if defined(CONFIG_SMBUS_INTEL_PCH_SMBALERT)
274 	k_work_init(&data->smb_alert_work, smbalert_work);
275 #endif /* CONFIG_SMBUS_INTEL_PCH_SMBALERT */
276 
277 #if defined(CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY)
278 	k_work_init(&data->host_notify_work, host_notify_work);
279 #endif /* CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY */
280 
281 	config->config_func(dev);
282 
283 	if (pch_configure(dev, SMBUS_MODE_CONTROLLER)) {
284 		LOG_ERR("SMBus: Cannot set default configuration");
285 		return -EIO;
286 	}
287 
288 	return 0;
289 }
290 
pch_prepare_transfer(const struct device * dev)291 static int pch_prepare_transfer(const struct device *dev)
292 {
293 	uint8_t hsts;
294 
295 	hsts = pch_reg_read(dev, PCH_SMBUS_HSTS);
296 
297 	pch_dump_register_hsts(hsts);
298 
299 	if (hsts & PCH_SMBUS_HSTS_HOST_BUSY) {
300 		LOG_ERR("Return BUSY status");
301 		return -EBUSY;
302 	}
303 
304 	/* Check and clear HSTS status bits */
305 	hsts &= PCH_SMBUS_HSTS_ERROR | PCH_SMBUS_HSTS_BYTE_DONE |
306 		PCH_SMBUS_HSTS_INTERRUPT;
307 	if (hsts) {
308 		pch_reg_write(dev, PCH_SMBUS_HSTS, hsts);
309 	}
310 
311 	/* TODO: Clear also CRC check bits */
312 
313 	return 0;
314 }
315 
pch_check_status(const struct device * dev)316 static int pch_check_status(const struct device *dev)
317 {
318 	struct pch_data *data = dev->data;
319 	uint8_t status = data->status;
320 
321 	/**
322 	 * Device Error means following:
323 	 * - unsupported Command Field Unclaimed Cycle
324 	 * - Host Device timeout
325 	 * - CRC Error
326 	 */
327 	if (status & PCH_SMBUS_HSTS_DEV_ERROR) {
328 		uint8_t auxs = pch_reg_read(dev, PCH_SMBUS_AUXS);
329 
330 		LOG_WRN("Device Error (DERR) received");
331 
332 		if (auxs & PCH_SMBUS_AUXS_CRC_ERROR) {
333 			LOG_DBG("AUXS register 0x%02x", auxs);
334 			/* Clear CRC error status bit */
335 			pch_reg_write(dev, PCH_SMBUS_AUXS,
336 				      PCH_SMBUS_AUXS_CRC_ERROR);
337 		}
338 
339 		return -EIO;
340 	}
341 
342 	/**
343 	 * Transaction collision, several masters are trying to access
344 	 * the bus and PCH detects arbitration lost.
345 	 */
346 	if (status & PCH_SMBUS_HSTS_BUS_ERROR) {
347 		LOG_WRN("Bus Error (BERR) received");
348 
349 		return -EAGAIN;
350 	}
351 
352 	/**
353 	 * Source of interrupt is failed bus transaction. This is set in
354 	 * response to KILL set to terminate the host transaction
355 	 */
356 	if (status & PCH_SMBUS_HSTS_FAILED) {
357 		LOG_WRN("Failed (FAIL) received");
358 
359 		return -EIO;
360 	}
361 
362 	return 0;
363 }
364 
pch_smbus_block_start(const struct device * dev,uint16_t periph_addr,uint8_t rw,uint8_t command,uint8_t count,uint8_t * buf,uint8_t protocol)365 static int pch_smbus_block_start(const struct device *dev, uint16_t periph_addr,
366 				 uint8_t rw, uint8_t command, uint8_t count,
367 				 uint8_t *buf, uint8_t protocol)
368 {
369 	uint8_t reg;
370 	int ret;
371 
372 	LOG_DBG("addr %x rw %d command %x", periph_addr, rw, command);
373 
374 	/* Set TSA register */
375 	reg = PCH_SMBUS_TSA_ADDR_SET(periph_addr);
376 	reg |= rw & SMBUS_MSG_RW_MASK;
377 	pch_reg_write(dev, PCH_SMBUS_TSA, reg);
378 
379 	/* Set HCMD register */
380 	pch_reg_write(dev, PCH_SMBUS_HCMD, command);
381 
382 	/* Enable 32-byte buffer mode (E32b) to send block of data */
383 	reg = pch_reg_read(dev, PCH_SMBUS_AUXC);
384 	reg |= PCH_SMBUS_AUXC_EN_32BUF;
385 	pch_reg_write(dev, PCH_SMBUS_AUXC, reg);
386 
387 	/* In E32B mode read and write to PCH_SMBUS_HBD translates to
388 	 * read and write to 32 byte storage array, index needs to be
389 	 * cleared by reading HCTL
390 	 */
391 	reg = pch_reg_read(dev, PCH_SMBUS_HCTL);
392 	ARG_UNUSED(reg); /* Avoid 'Dead assignment' warning */
393 
394 	if (rw == SMBUS_MSG_WRITE) {
395 		/* Write count */
396 		pch_reg_write(dev, PCH_SMBUS_HD0, count);
397 
398 		/* Write data to send */
399 		for (int i = 0; i < count; i++) {
400 			pch_reg_write(dev, PCH_SMBUS_HBD, buf[i]);
401 		}
402 	}
403 
404 	ret = pch_prepare_transfer(dev);
405 	if (ret < 0) {
406 		return ret;
407 	}
408 
409 	/* Set HCTL register */
410 	reg = PCH_SMBUS_HCTL_CMD_SET(protocol);
411 	reg |= PCH_SMBUS_HCTL_START;
412 	reg |= PCH_SMBUS_HCTL_INTR_EN;
413 	pch_reg_write(dev, PCH_SMBUS_HCTL, reg);
414 
415 	return 0;
416 }
417 
418 /* Start PCH SMBus operation */
pch_smbus_start(const struct device * dev,uint16_t periph_addr,enum smbus_direction rw,uint8_t command,uint8_t * buf,uint8_t protocol)419 static int pch_smbus_start(const struct device *dev, uint16_t periph_addr,
420 			   enum smbus_direction rw, uint8_t command,
421 			   uint8_t *buf, uint8_t protocol)
422 {
423 	uint8_t reg;
424 	int ret;
425 
426 	LOG_DBG("addr 0x%02x rw %d command %x", periph_addr, rw, command);
427 
428 	/* Set TSA register */
429 	reg = PCH_SMBUS_TSA_ADDR_SET(periph_addr);
430 	reg |= rw & SMBUS_MSG_RW_MASK;
431 	pch_reg_write(dev, PCH_SMBUS_TSA, reg);
432 
433 	/* Write command for every but QUICK op */
434 	if (protocol != SMBUS_CMD_QUICK) {
435 		/* Set HCMD register */
436 		pch_reg_write(dev, PCH_SMBUS_HCMD, command);
437 
438 		/* Set Host Data 0 (HD0) register */
439 		if (rw == SMBUS_MSG_WRITE && protocol != SMBUS_CMD_BYTE) {
440 			pch_reg_write(dev, PCH_SMBUS_HD0, buf[0]);
441 
442 			/* If we need to write second byte */
443 			if (protocol == SMBUS_CMD_WORD_DATA ||
444 			    protocol == SMBUS_CMD_PROC_CALL) {
445 				pch_reg_write(dev, PCH_SMBUS_HD1, buf[1]);
446 			}
447 		}
448 	}
449 
450 	ret = pch_prepare_transfer(dev);
451 	if (ret < 0) {
452 		return ret;
453 	}
454 
455 	/* Set HCTL register */
456 	reg = PCH_SMBUS_HCTL_CMD_SET(protocol);
457 	reg |= PCH_SMBUS_HCTL_START;
458 	reg |= PCH_SMBUS_HCTL_INTR_EN;
459 	pch_reg_write(dev, PCH_SMBUS_HCTL, reg);
460 
461 	return 0;
462 }
463 
464 /* Implementation of PCH SMBus API */
465 
466 /* Implementation of SMBus Quick */
pch_smbus_quick(const struct device * dev,uint16_t periph_addr,enum smbus_direction rw)467 static int pch_smbus_quick(const struct device *dev, uint16_t periph_addr,
468 			   enum smbus_direction rw)
469 {
470 	struct pch_data *data = dev->data;
471 	int ret;
472 
473 	LOG_DBG("dev %p addr 0x%02x direction %x", dev, periph_addr, rw);
474 
475 	k_mutex_lock(&data->mutex, K_FOREVER);
476 
477 	ret = pch_smbus_start(dev, periph_addr, rw, 0, NULL, SMBUS_CMD_QUICK);
478 	if (ret < 0) {
479 		goto unlock;
480 	}
481 
482 	/* Wait for completion from ISR */
483 	ret = k_sem_take(&data->completion_sync, K_MSEC(30));
484 	if (ret != 0) {
485 		LOG_ERR("SMBus Quick timed out");
486 		ret = -ETIMEDOUT;
487 		goto unlock;
488 	}
489 
490 	ret = pch_check_status(dev);
491 
492 unlock:
493 	k_mutex_unlock(&data->mutex);
494 
495 	return ret;
496 }
497 
498 /* Implementation of SMBus Byte Write */
pch_smbus_byte_write(const struct device * dev,uint16_t periph_addr,uint8_t command)499 static int pch_smbus_byte_write(const struct device *dev, uint16_t periph_addr,
500 				uint8_t command)
501 {
502 	struct pch_data *data = dev->data;
503 	int ret;
504 
505 	LOG_DBG("dev %p addr 0x%02x command 0x%02x", dev, periph_addr, command);
506 
507 	k_mutex_lock(&data->mutex, K_FOREVER);
508 
509 	ret = pch_smbus_start(dev, periph_addr, SMBUS_MSG_WRITE, command, NULL,
510 			      SMBUS_CMD_BYTE);
511 	if (ret < 0) {
512 		goto unlock;
513 	}
514 
515 	/* Wait for completion from ISR */
516 	ret = k_sem_take(&data->completion_sync, K_MSEC(30));
517 	if (ret != 0) {
518 		LOG_ERR("SMBus Byte Write timed out");
519 		ret = -ETIMEDOUT;
520 		goto unlock;
521 	}
522 
523 	ret = pch_check_status(dev);
524 
525 unlock:
526 	k_mutex_unlock(&data->mutex);
527 
528 	return ret;
529 }
530 
531 /* Implementation of SMBus Byte Read */
pch_smbus_byte_read(const struct device * dev,uint16_t periph_addr,uint8_t * byte)532 static int pch_smbus_byte_read(const struct device *dev, uint16_t periph_addr,
533 			       uint8_t *byte)
534 {
535 	struct pch_data *data = dev->data;
536 	int ret;
537 
538 	LOG_DBG("dev %p addr 0x%02x", dev, periph_addr);
539 
540 	k_mutex_lock(&data->mutex, K_FOREVER);
541 
542 	ret = pch_smbus_start(dev, periph_addr, SMBUS_MSG_READ, 0, NULL,
543 			      SMBUS_CMD_BYTE);
544 	if (ret < 0) {
545 		goto unlock;
546 	}
547 
548 	/* Wait for completion from ISR */
549 	ret = k_sem_take(&data->completion_sync, K_MSEC(30));
550 	if (ret != 0) {
551 		LOG_ERR("SMBus Byte Read timed out");
552 		ret = -ETIMEDOUT;
553 		goto unlock;
554 	}
555 
556 	ret = pch_check_status(dev);
557 	if (ret < 0) {
558 		goto unlock;
559 	}
560 
561 	*byte = pch_reg_read(dev, PCH_SMBUS_HD0);
562 
563 unlock:
564 	k_mutex_unlock(&data->mutex);
565 
566 	return ret;
567 }
568 
569 /* Implementation of SMBus Byte Data Write */
pch_smbus_byte_data_write(const struct device * dev,uint16_t periph_addr,uint8_t command,uint8_t byte)570 static int pch_smbus_byte_data_write(const struct device *dev,
571 				     uint16_t periph_addr,
572 				     uint8_t command, uint8_t byte)
573 {
574 	struct pch_data *data = dev->data;
575 	int ret;
576 
577 	LOG_DBG("dev %p addr 0x%02x command 0x%02x", dev, periph_addr, command);
578 
579 	k_mutex_lock(&data->mutex, K_FOREVER);
580 
581 	ret = pch_smbus_start(dev, periph_addr, SMBUS_MSG_WRITE, command,
582 			      &byte, SMBUS_CMD_BYTE_DATA);
583 	if (ret < 0) {
584 		goto unlock;
585 	}
586 
587 	/* Wait for completion from ISR */
588 	ret = k_sem_take(&data->completion_sync, K_MSEC(30));
589 	if (ret != 0) {
590 		LOG_ERR("SMBus Byte Data Write timed out");
591 		ret = -ETIMEDOUT;
592 		goto unlock;
593 	}
594 
595 	ret = pch_check_status(dev);
596 
597 unlock:
598 	k_mutex_unlock(&data->mutex);
599 
600 	return ret;
601 }
602 
603 /* Implementation of SMBus Byte Data Read */
pch_smbus_byte_data_read(const struct device * dev,uint16_t periph_addr,uint8_t command,uint8_t * byte)604 static int pch_smbus_byte_data_read(const struct device *dev,
605 				    uint16_t periph_addr,
606 				    uint8_t command, uint8_t *byte)
607 {
608 	struct pch_data *data = dev->data;
609 	int ret;
610 
611 	LOG_DBG("dev %p addr 0x%02x command 0x%02x", dev, periph_addr, command);
612 
613 	k_mutex_lock(&data->mutex, K_FOREVER);
614 
615 	ret = pch_smbus_start(dev, periph_addr, SMBUS_MSG_READ, command,
616 			      NULL, SMBUS_CMD_BYTE_DATA);
617 	if (ret < 0) {
618 		goto unlock;
619 	}
620 
621 	/* Wait for completion from ISR */
622 	ret = k_sem_take(&data->completion_sync, K_MSEC(30));
623 	if (ret != 0) {
624 		LOG_ERR("SMBus Byte Data Read timed out");
625 		ret = -ETIMEDOUT;
626 		goto unlock;
627 	}
628 
629 	ret = pch_check_status(dev);
630 	if (ret < 0) {
631 		goto unlock;
632 	}
633 
634 	*byte = pch_reg_read(dev, PCH_SMBUS_HD0);
635 
636 unlock:
637 	k_mutex_unlock(&data->mutex);
638 
639 	return ret;
640 }
641 
642 /* Implementation of SMBus Word Data Write */
pch_smbus_word_data_write(const struct device * dev,uint16_t periph_addr,uint8_t command,uint16_t word)643 static int pch_smbus_word_data_write(const struct device *dev,
644 				     uint16_t periph_addr,
645 				     uint8_t command, uint16_t word)
646 {
647 	struct pch_data *data = dev->data;
648 	int ret;
649 
650 	LOG_DBG("dev %p addr 0x%02x command 0x%02x", dev, periph_addr, command);
651 
652 	k_mutex_lock(&data->mutex, K_FOREVER);
653 
654 	ret = pch_smbus_start(dev, periph_addr, SMBUS_MSG_WRITE, command,
655 			      (uint8_t *)&word, SMBUS_CMD_WORD_DATA);
656 	if (ret < 0) {
657 		goto unlock;
658 	}
659 
660 	/* Wait for completion from ISR */
661 	ret = k_sem_take(&data->completion_sync, K_MSEC(30));
662 	if (ret != 0) {
663 		LOG_ERR("SMBus Word Data Write timed out");
664 		ret = -ETIMEDOUT;
665 		goto unlock;
666 	}
667 
668 	ret = pch_check_status(dev);
669 
670 unlock:
671 	k_mutex_unlock(&data->mutex);
672 
673 	return ret;
674 }
675 
676 /* Implementation of SMBus Word Data Read */
pch_smbus_word_data_read(const struct device * dev,uint16_t periph_addr,uint8_t command,uint16_t * word)677 static int pch_smbus_word_data_read(const struct device *dev,
678 				    uint16_t periph_addr,
679 				    uint8_t command, uint16_t *word)
680 {
681 	struct pch_data *data = dev->data;
682 	uint8_t *p = (uint8_t *)word;
683 	int ret;
684 
685 	LOG_DBG("dev %p addr 0x%02x command 0x%02x", dev, periph_addr, command);
686 
687 	k_mutex_lock(&data->mutex, K_FOREVER);
688 
689 	ret = pch_smbus_start(dev, periph_addr, SMBUS_MSG_READ, command,
690 			      NULL, SMBUS_CMD_WORD_DATA);
691 	if (ret < 0) {
692 		goto unlock;
693 	}
694 
695 	/* Wait for completion from ISR */
696 	ret = k_sem_take(&data->completion_sync, K_MSEC(30));
697 	if (ret != 0) {
698 		LOG_ERR("SMBus Word Data Read timed out");
699 		ret = -ETIMEDOUT;
700 		goto unlock;
701 	}
702 
703 	ret = pch_check_status(dev);
704 	if (ret < 0) {
705 		goto unlock;
706 	}
707 
708 	p[0] = pch_reg_read(dev, PCH_SMBUS_HD0);
709 	p[1] = pch_reg_read(dev, PCH_SMBUS_HD1);
710 
711 unlock:
712 	k_mutex_unlock(&data->mutex);
713 
714 	return ret;
715 }
716 
717 /* Implementation of SMBus Process Call */
pch_smbus_pcall(const struct device * dev,uint16_t periph_addr,uint8_t command,uint16_t send_word,uint16_t * recv_word)718 static int pch_smbus_pcall(const struct device *dev,
719 			   uint16_t periph_addr, uint8_t command,
720 			   uint16_t send_word, uint16_t *recv_word)
721 {
722 	struct pch_data *data = dev->data;
723 	uint8_t *p = (uint8_t *)recv_word;
724 	int ret;
725 
726 	LOG_DBG("dev %p addr 0x%02x command 0x%02x", dev, periph_addr, command);
727 
728 	k_mutex_lock(&data->mutex, K_FOREVER);
729 
730 	ret = pch_smbus_start(dev, periph_addr, SMBUS_MSG_WRITE, command,
731 			      (uint8_t *)&send_word, SMBUS_CMD_PROC_CALL);
732 	if (ret < 0) {
733 		goto unlock;
734 	}
735 
736 	/* Wait for completion from ISR */
737 	ret = k_sem_take(&data->completion_sync, K_MSEC(30));
738 	if (ret != 0) {
739 		LOG_ERR("SMBus Proc Call timed out");
740 		ret = -ETIMEDOUT;
741 		goto unlock;
742 	}
743 
744 	ret = pch_check_status(dev);
745 	if (ret < 0) {
746 		goto unlock;
747 	}
748 
749 	p[0] = pch_reg_read(dev, PCH_SMBUS_HD0);
750 	p[1] = pch_reg_read(dev, PCH_SMBUS_HD1);
751 
752 unlock:
753 	k_mutex_unlock(&data->mutex);
754 
755 	return ret;
756 }
757 
758 /* Implementation of SMBus Block Write */
pch_smbus_block_write(const struct device * dev,uint16_t periph_addr,uint8_t command,uint8_t count,uint8_t * buf)759 static int pch_smbus_block_write(const struct device *dev, uint16_t periph_addr,
760 				 uint8_t command, uint8_t count, uint8_t *buf)
761 {
762 	struct pch_data *data = dev->data;
763 	int ret;
764 
765 	LOG_DBG("dev %p addr 0x%02x command 0x%02x count %u",
766 		dev, periph_addr, command, count);
767 
768 	k_mutex_lock(&data->mutex, K_FOREVER);
769 
770 	ret = pch_smbus_block_start(dev, periph_addr, SMBUS_MSG_WRITE, command,
771 				    count, buf, SMBUS_CMD_BLOCK);
772 	if (ret < 0) {
773 		goto unlock;
774 	}
775 
776 	/* Wait for completion from ISR */
777 	ret = k_sem_take(&data->completion_sync, K_MSEC(30));
778 	if (ret != 0) {
779 		LOG_ERR("SMBus Block Write timed out");
780 		ret = -ETIMEDOUT;
781 		goto unlock;
782 	}
783 
784 	ret = pch_check_status(dev);
785 
786 unlock:
787 	k_mutex_unlock(&data->mutex);
788 
789 	return ret;
790 }
791 
792 /* Implementation of SMBus Block Read */
pch_smbus_block_read(const struct device * dev,uint16_t periph_addr,uint8_t command,uint8_t * count,uint8_t * buf)793 static int pch_smbus_block_read(const struct device *dev, uint16_t periph_addr,
794 				uint8_t command, uint8_t *count, uint8_t *buf)
795 {
796 	struct pch_data *data = dev->data;
797 	int ret;
798 
799 	LOG_DBG("dev %p addr 0x%02x command 0x%02x",
800 		dev, periph_addr, command);
801 
802 	k_mutex_lock(&data->mutex, K_FOREVER);
803 
804 	ret = pch_smbus_block_start(dev, periph_addr, SMBUS_MSG_READ, command,
805 				    0, buf, SMBUS_CMD_BLOCK);
806 	if (ret < 0) {
807 		goto unlock;
808 	}
809 
810 	/* Wait for completion from ISR */
811 	ret = k_sem_take(&data->completion_sync, K_MSEC(30));
812 	if (ret != 0) {
813 		LOG_ERR("SMBus Block Read timed out");
814 		ret = -ETIMEDOUT;
815 		goto unlock;
816 	}
817 
818 	ret = pch_check_status(dev);
819 	if (ret < 0) {
820 		goto unlock;
821 	}
822 
823 	*count = pch_reg_read(dev, PCH_SMBUS_HD0);
824 	if (*count == 0 || *count > SMBUS_BLOCK_BYTES_MAX) {
825 		ret = -ENODATA;
826 		goto unlock;
827 	}
828 
829 	for (int i = 0; i < *count; i++) {
830 		buf[i] = pch_reg_read(dev, PCH_SMBUS_HBD);
831 	}
832 
833 unlock:
834 	k_mutex_unlock(&data->mutex);
835 
836 	return ret;
837 }
838 
839 /* Implementation of SMBus Block Process Call */
pch_smbus_block_pcall(const struct device * dev,uint16_t periph_addr,uint8_t command,uint8_t send_count,uint8_t * send_buf,uint8_t * recv_count,uint8_t * recv_buf)840 static int pch_smbus_block_pcall(const struct device *dev,
841 				 uint16_t periph_addr, uint8_t command,
842 				 uint8_t send_count, uint8_t *send_buf,
843 				 uint8_t *recv_count, uint8_t *recv_buf)
844 {
845 	struct pch_data *data = dev->data;
846 	int ret;
847 
848 	LOG_DBG("dev %p addr 0x%02x command 0x%02x",
849 		dev, periph_addr, command);
850 
851 	k_mutex_lock(&data->mutex, K_FOREVER);
852 
853 	ret = pch_smbus_block_start(dev, periph_addr, SMBUS_MSG_WRITE, command,
854 				    send_count, send_buf, SMBUS_CMD_BLOCK_PROC);
855 	if (ret < 0) {
856 		goto unlock;
857 	}
858 
859 	/* Wait for completion from ISR */
860 	ret = k_sem_take(&data->completion_sync, K_MSEC(30));
861 	if (ret != 0) {
862 		LOG_ERR("SMBus Block Process Call timed out");
863 		ret = -ETIMEDOUT;
864 		goto unlock;
865 	}
866 
867 	ret = pch_check_status(dev);
868 	if (ret < 0) {
869 		goto unlock;
870 	}
871 
872 	*recv_count = pch_reg_read(dev, PCH_SMBUS_HD0);
873 	if (*recv_count == 0 ||
874 	    *recv_count + send_count > SMBUS_BLOCK_BYTES_MAX) {
875 		ret = -ENODATA;
876 		goto unlock;
877 	}
878 
879 	for (int i = 0; i < *recv_count; i++) {
880 		recv_buf[i] = pch_reg_read(dev, PCH_SMBUS_HBD);
881 	}
882 
883 unlock:
884 	k_mutex_unlock(&data->mutex);
885 
886 	return ret;
887 }
888 
889 static const struct smbus_driver_api funcs = {
890 	.configure = pch_configure,
891 	.get_config = pch_get_config,
892 	.smbus_quick = pch_smbus_quick,
893 	.smbus_byte_write = pch_smbus_byte_write,
894 	.smbus_byte_read = pch_smbus_byte_read,
895 	.smbus_byte_data_write = pch_smbus_byte_data_write,
896 	.smbus_byte_data_read = pch_smbus_byte_data_read,
897 	.smbus_word_data_write = pch_smbus_word_data_write,
898 	.smbus_word_data_read = pch_smbus_word_data_read,
899 	.smbus_pcall = pch_smbus_pcall,
900 	.smbus_block_write = pch_smbus_block_write,
901 	.smbus_block_read = pch_smbus_block_read,
902 	.smbus_block_pcall = pch_smbus_block_pcall,
903 #if defined(CONFIG_SMBUS_INTEL_PCH_SMBALERT)
904 	.smbus_smbalert_set_cb = pch_smbus_smbalert_set_sb,
905 	.smbus_smbalert_remove_cb = pch_smbus_smbalert_remove_sb,
906 #endif /* CONFIG_SMBUS_INTEL_PCH_SMBALERT */
907 #if defined(CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY)
908 	.smbus_host_notify_set_cb = pch_smbus_host_notify_set_cb,
909 	.smbus_host_notify_remove_cb = pch_smbus_host_notify_remove_cb,
910 #endif /* CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY */
911 };
912 
smbus_isr(const struct device * dev)913 static void smbus_isr(const struct device *dev)
914 {
915 	const struct pch_config * const config = dev->config;
916 	struct pch_data *data = dev->data;
917 	uint32_t sts;
918 	uint8_t status;
919 
920 	sts = pcie_conf_read(config->pcie->bdf, PCIE_CONF_CMDSTAT);
921 	if (!(sts & PCIE_CONF_CMDSTAT_INTERRUPT)) {
922 		LOG_ERR("Not our interrupt");
923 		return;
924 	}
925 
926 	/**
927 	 * Handle first Host Notify since for that we need to read SSTS
928 	 * register and for all other sources HSTS.
929 	 *
930 	 * Intel PCH implements Host Notify protocol in hardware.
931 	 */
932 #if defined(CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY)
933 	if (data->config & SMBUS_MODE_HOST_NOTIFY) {
934 		status = pch_reg_read(dev, PCH_SMBUS_SSTS);
935 		if (status & PCH_SMBUS_SSTS_HNS) {
936 			/* Notify address */
937 			data->notify_addr =
938 				pch_reg_read(dev, PCH_SMBUS_NDA) >> 1;
939 
940 			/* Notify data */
941 			data->notify_data = pch_reg_read(dev, PCH_SMBUS_NDLB);
942 			data->notify_data |=
943 				pch_reg_read(dev, PCH_SMBUS_NDHB) << 8;
944 
945 			k_work_submit(&data->host_notify_work);
946 
947 			/* Clear Host Notify */
948 			pch_reg_write(dev, PCH_SMBUS_SSTS, PCH_SMBUS_SSTS_HNS);
949 
950 			return;
951 		}
952 	}
953 #endif /* CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY */
954 
955 	status = pch_reg_read(dev, PCH_SMBUS_HSTS);
956 
957 	/* HSTS dump if logging is enabled */
958 	pch_dump_register_hsts(status);
959 
960 	if (status & PCH_SMBUS_HSTS_BYTE_DONE) {
961 		LOG_WRN("BYTE_DONE interrupt is not used");
962 	}
963 
964 	/* Handle SMBALERT# signal */
965 #if defined(CONFIG_SMBUS_INTEL_PCH_SMBALERT)
966 	if (data->config & SMBUS_MODE_SMBALERT &&
967 	    status & PCH_SMBUS_HSTS_SMB_ALERT) {
968 		k_work_submit(&data->smb_alert_work);
969 	}
970 #endif /* CONFIG_SMBUS_INTEL_PCH_SMBALERT */
971 
972 	/* Clear IRQ sources */
973 	pch_reg_write(dev, PCH_SMBUS_HSTS, status);
974 
975 	data->status = status;
976 
977 	k_sem_give(&data->completion_sync);
978 }
979 
980 /* Device macro initialization  / DTS hackery */
981 
982 #define SMBUS_PCH_IRQ_FLAGS(n)                                                 \
983 	COND_CODE_1(DT_INST_IRQ_HAS_CELL(n, sense),                            \
984 		    (DT_INST_IRQ(n, sense)),                                   \
985 		    (0))
986 
987 #define SMBUS_IRQ_CONFIG(n)                                                    \
988 	BUILD_ASSERT(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS),                    \
989 		     "SMBus PCIe requires dynamic interrupts");                \
990 	static void pch_config_##n(const struct device *dev)                   \
991 	{                                                                      \
992 		const struct pch_config * const config = dev->config;          \
993 		unsigned int irq;                                              \
994 		if (DT_INST_IRQN(n) == PCIE_IRQ_DETECT) {                      \
995 			irq = pcie_alloc_irq(config->pcie->bdf);               \
996 			if (irq == PCIE_CONF_INTR_IRQ_NONE) {                  \
997 				return;                                        \
998 			}                                                      \
999 		} else {                                                       \
1000 			irq = DT_INST_IRQN(n);                                 \
1001 			pcie_conf_write(config->pcie->bdf,                     \
1002 					PCIE_CONF_INTR, irq);                  \
1003 		}                                                              \
1004 		pcie_connect_dynamic_irq(config->pcie->bdf, irq,               \
1005 					 DT_INST_IRQ(n, priority),             \
1006 					 (void (*)(const void *))smbus_isr,    \
1007 					 DEVICE_DT_INST_GET(n),                \
1008 					 SMBUS_PCH_IRQ_FLAGS(n));              \
1009 		pcie_irq_enable(config->pcie->bdf, irq);                       \
1010 		LOG_DBG("Configure irq %d", irq);                              \
1011 	}
1012 
1013 #define SMBUS_DEVICE_INIT(n)                                                   \
1014 	DEVICE_PCIE_INST_DECLARE(n);                                           \
1015 	static void pch_config_##n(const struct device *dev);                  \
1016 	static const struct pch_config pch_config_data_##n = {                 \
1017 		DEVICE_PCIE_INST_INIT(n, pcie),                                \
1018 		.config_func = pch_config_##n,                                 \
1019 	};                                                                     \
1020 	static struct pch_data smbus_##n##_data;                               \
1021 	SMBUS_DEVICE_DT_INST_DEFINE(n, pch_smbus_init, NULL,                   \
1022 				    &smbus_##n##_data, &pch_config_data_##n,   \
1023 				    POST_KERNEL, CONFIG_SMBUS_INIT_PRIORITY,   \
1024 				    &funcs);                                   \
1025 	SMBUS_IRQ_CONFIG(n);
1026 
1027 DT_INST_FOREACH_STATUS_OKAY(SMBUS_DEVICE_INIT)
1028