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