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