Lines Matching +full:temperature +full:- +full:lookup +full:- +full:table
7 * Copyright (C) 2016-2018 T-Platforms JSC All Rights Reserved.
36 * IDT PCIe-switch NTB Linux driver
39 * Serge Semin <fancer.lancer@gmail.com>, <Sergey.Semin@t-platforms.ru>
59 #include <linux/hwmon-sysfs.h>
65 #define NTB_DESC "IDT PCI-E Non-Transparent Bridge Driver"
72 MODULE_AUTHOR("T-platforms");
75 * NT Endpoint registers table simplifying a loop access to the functionally
98 * NT Endpoint ports data table with the corresponding pcie command, link
99 * status, control and BAR-related registers
241 * IDT PCIe-switch partitions table with the corresponding control, status
277 * 1. IDT PCIe-switch registers IO-functions
279 * Beside ordinary configuration space registers IDT PCIe-switch expose
281 * device ports as well as being notified of some switch-related events.
283 * PCIe-switch functions are mapped to the Global Address space, so each
284 * function can determine a configuration of any other PCI-function.
292 * idt_nt_write() - PCI configuration space registers write method
297 * IDT PCIe-switch registers are all Little endian.
310 iowrite32(data, ndev->cfgspc + (ptrdiff_t)reg); in idt_nt_write()
314 * idt_nt_read() - PCI configuration space registers read method
318 * IDT PCIe-switch Global configuration registers are all Little endian.
332 return ioread32(ndev->cfgspc + (ptrdiff_t)reg); in idt_nt_read()
336 * idt_sw_write() - Global registers write method
341 * IDT PCIe-switch Global configuration registers are all Little endian.
356 spin_lock_irqsave(&ndev->gasa_lock, irqflags); in idt_sw_write()
358 iowrite32((u32)reg, ndev->cfgspc + (ptrdiff_t)IDT_NT_GASAADDR); in idt_sw_write()
360 iowrite32(data, ndev->cfgspc + (ptrdiff_t)IDT_NT_GASADATA); in idt_sw_write()
362 spin_unlock_irqrestore(&ndev->gasa_lock, irqflags); in idt_sw_write()
366 * idt_sw_read() - Global registers read method
370 * IDT PCIe-switch Global configuration registers are all Little endian.
387 spin_lock_irqsave(&ndev->gasa_lock, irqflags); in idt_sw_read()
389 iowrite32((u32)reg, ndev->cfgspc + (ptrdiff_t)IDT_NT_GASAADDR); in idt_sw_read()
391 data = ioread32(ndev->cfgspc + (ptrdiff_t)IDT_NT_GASADATA); in idt_sw_read()
393 spin_unlock_irqrestore(&ndev->gasa_lock, irqflags); in idt_sw_read()
399 * idt_reg_set_bits() - set bits of a passed register
422 return -EINVAL; in idt_reg_set_bits()
435 * idt_reg_clear_bits() - clear bits of a passed register
468 * IDT PCIe-switches can have from 3 up to 8 ports with possible
469 * NT-functions enabled. So all the possible ports need to be scanned looking
475 * idt_scan_ports() - scan IDT PCIe-switch ports collecting info in the tables
487 ndev->port = GET_FIELD(PCIELCAP_PORTNUM, data); in idt_scan_ports()
490 portsts = idt_sw_read(ndev, portdata_tbl[ndev->port].sts); in idt_scan_ports()
491 ndev->part = GET_FIELD(SWPORTxSTS_SWPART, portsts); in idt_scan_ports()
493 /* Initialize port/partition -> index tables with invalid values */ in idt_scan_ports()
494 memset(ndev->port_idx_map, -EINVAL, sizeof(ndev->port_idx_map)); in idt_scan_ports()
495 memset(ndev->part_idx_map, -EINVAL, sizeof(ndev->part_idx_map)); in idt_scan_ports()
499 * NT-function activated in idt_scan_ports()
501 ndev->peer_cnt = 0; in idt_scan_ports()
502 for (pidx = 0; pidx < ndev->swcfg->port_cnt; pidx++) { in idt_scan_ports()
503 port = ndev->swcfg->ports[pidx]; in idt_scan_ports()
505 if (port == ndev->port) in idt_scan_ports()
521 ndev->peers[ndev->peer_cnt].port = port; in idt_scan_ports()
522 ndev->peers[ndev->peer_cnt].part = part; in idt_scan_ports()
523 /* Fill in the port/partition -> index tables */ in idt_scan_ports()
524 ndev->port_idx_map[port] = ndev->peer_cnt; in idt_scan_ports()
525 ndev->part_idx_map[part] = ndev->peer_cnt; in idt_scan_ports()
526 ndev->peer_cnt++; in idt_scan_ports()
530 dev_dbg(&ndev->ntb.pdev->dev, "Local port: %hhu, num of peers: %hhu\n", in idt_scan_ports()
531 ndev->port, ndev->peer_cnt); in idt_scan_ports()
534 if (ndev->peer_cnt == 0) { in idt_scan_ports()
535 dev_warn(&ndev->ntb.pdev->dev, "No active peer found\n"); in idt_scan_ports()
536 return -ENODEV; in idt_scan_ports()
543 * idt_ntb_port_number() - get the local port number
552 return ndev->port; in idt_ntb_port_number()
556 * idt_ntb_peer_port_count() - get the number of peer ports
559 * Return the count of detected peer NT-functions.
567 return ndev->peer_cnt; in idt_ntb_peer_port_count()
571 * idt_ntb_peer_port_number() - get peer port by given index
581 if (pidx < 0 || ndev->peer_cnt <= pidx) in idt_ntb_peer_port_number()
582 return -EINVAL; in idt_ntb_peer_port_number()
584 /* Return the detected NT-function port number */ in idt_ntb_peer_port_number()
585 return ndev->peers[pidx].port; in idt_ntb_peer_port_number()
589 * idt_ntb_peer_port_idx() - get peer port index by given port number
593 * Internal port -> index table is pre-initialized with -EINVAL values,
596 * Return: peer NT-function port index or negative error
603 return -EINVAL; in idt_ntb_peer_port_idx()
605 return ndev->port_idx_map[port]; in idt_ntb_peer_port_idx()
610 * There is no any ready-to-use method to have peer ports notified if NTB
616 * Additionally each of active NT-functions is subscribed to PCIe-link
624 * idt_init_link() - Initialize NTB link state notification subsystem
628 * needed to enable IRQ-based notifications of PCIe Link Up/Down and
640 /* Initialize spin locker of Mapping Table access registers */ in idt_init_link()
641 spin_lock_init(&ndev->mtbl_lock); in idt_init_link()
644 port_mask = ~BIT(ndev->port); in idt_init_link()
645 part_mask = ~BIT(ndev->part); in idt_init_link()
646 for (pidx = 0; pidx < ndev->peer_cnt; pidx++) { in idt_init_link()
647 port_mask &= ~BIT(ndev->peers[pidx].port); in idt_init_link()
648 part_mask &= ~BIT(ndev->peers[pidx].part); in idt_init_link()
652 idt_sw_write(ndev, IDT_SW_SELINKUPSTS, (u32)-1); in idt_init_link()
653 idt_sw_write(ndev, IDT_SW_SELINKDNSTS, (u32)-1); in idt_init_link()
654 idt_sw_write(ndev, IDT_SW_SEGSIGSTS, (u32)-1); in idt_init_link()
656 /* Unmask NT-activated partitions to receive Global Switch events */ in idt_init_link()
659 /* Enable PCIe Link Up events of NT-activated ports */ in idt_init_link()
662 /* Enable PCIe Link Down events of NT-activated ports */ in idt_init_link()
665 /* Unmask NT-activated partitions to receive Global Signal events */ in idt_init_link()
672 dev_dbg(&ndev->ntb.pdev->dev, "NTB link status events initialized"); in idt_init_link()
676 * idt_deinit_link() - deinitialize link subsystem
686 dev_dbg(&ndev->ntb.pdev->dev, "NTB link status events deinitialized"); in idt_deinit_link()
690 * idt_se_isr() - switch events ISR
692 * @ntint_sts: NT-function interrupt status
694 * This driver doesn't support IDT PCIe-switch dynamic reconfigurations,
697 * The method is called from PCIe ISR bottom-half routine.
707 idt_sw_write(ndev, IDT_SW_SELINKUPSTS, (u32)-1); in idt_se_isr()
708 idt_sw_write(ndev, IDT_SW_SELINKDNSTS, (u32)-1); in idt_se_isr()
709 idt_sw_write(ndev, IDT_SW_SEGSIGSTS, (u32)-1); in idt_se_isr()
714 dev_dbg(&ndev->ntb.pdev->dev, "SE IRQ detected %#08x (SESTS %#08x)", in idt_se_isr()
718 ntb_link_event(&ndev->ntb); in idt_se_isr()
722 * idt_ntb_local_link_enable() - enable the local NTB link.
726 * - enable Completion TLPs translation
727 * - initialize mapping table to enable the Request ID translation
728 * - notify peers of NTB link state change
742 * Set the corresponding NT Mapping table entry of port partition index in idt_ntb_local_link_enable()
746 SET_FIELD(NTMTBLDATA_PART, 0, ndev->part) | in idt_ntb_local_link_enable()
748 spin_lock_irqsave(&ndev->mtbl_lock, irqflags); in idt_ntb_local_link_enable()
749 idt_nt_write(ndev, IDT_NT_NTMTBLADDR, ndev->part); in idt_ntb_local_link_enable()
751 spin_unlock_irqrestore(&ndev->mtbl_lock, irqflags); in idt_ntb_local_link_enable()
755 idt_sw_write(ndev, IDT_SW_SEGSIGSTS, (u32)1 << ndev->part); in idt_ntb_local_link_enable()
759 * idt_ntb_local_link_disable() - disable the local NTB link.
763 * - disable Completion TLPs translation
764 * - clear corresponding mapping table entry
765 * - notify peers of NTB link state change
774 /* Clear the corresponding NT Mapping table entry */ in idt_ntb_local_link_disable()
775 spin_lock_irqsave(&ndev->mtbl_lock, irqflags); in idt_ntb_local_link_disable()
776 idt_nt_write(ndev, IDT_NT_NTMTBLADDR, ndev->part); in idt_ntb_local_link_disable()
778 spin_unlock_irqrestore(&ndev->mtbl_lock, irqflags); in idt_ntb_local_link_disable()
782 idt_sw_write(ndev, IDT_SW_SEGSIGSTS, (u32)1 << ndev->part); in idt_ntb_local_link_disable()
786 * idt_ntb_local_link_is_up() - test wethter local NTB link is up
790 * - Bus mastering is enabled
791 * - NTCTL has Completion TLPs translation enabled
792 * - Mapping table permits Request TLPs translation
794 * up while we are able to communicate with IDT PCIe-switch
813 /* Read Mapping table entry corresponding to the local partition */ in idt_ntb_local_link_is_up()
814 spin_lock_irqsave(&ndev->mtbl_lock, irqflags); in idt_ntb_local_link_is_up()
815 idt_nt_write(ndev, IDT_NT_NTMTBLADDR, ndev->part); in idt_ntb_local_link_is_up()
817 spin_unlock_irqrestore(&ndev->mtbl_lock, irqflags); in idt_ntb_local_link_is_up()
823 * idt_ntb_peer_link_is_up() - test whether peer NTB link is up
828 * - PCIe link is up
829 * - Bus mastering is enabled
830 * - NTCTL has Completion TLPs translation enabled
831 * - Mapping table permits Request TLPs translation
842 port = ndev->peers[pidx].port; in idt_ntb_peer_link_is_up()
859 /* Read Mapping table entry corresponding to the peer partition */ in idt_ntb_peer_link_is_up()
860 spin_lock_irqsave(&ndev->mtbl_lock, irqflags); in idt_ntb_peer_link_is_up()
861 idt_nt_write(ndev, IDT_NT_NTMTBLADDR, ndev->peers[pidx].part); in idt_ntb_peer_link_is_up()
863 spin_unlock_irqrestore(&ndev->mtbl_lock, irqflags); in idt_ntb_peer_link_is_up()
869 * idt_ntb_link_is_up() - get the current ntb link state (NTB API callback)
871 * @speed: OUT - The link speed expressed as PCIe generation number.
872 * @width: OUT - The link width expressed as the number of PCIe lanes.
902 for (pidx = 0; pidx < ndev->peer_cnt; pidx++) { in idt_ntb_link_is_up()
911 * idt_ntb_link_enable() - enable local port ntb link (NTB API callback)
928 dev_dbg(&ndev->ntb.pdev->dev, "Local NTB link enabled"); in idt_ntb_link_enable()
934 * idt_ntb_link_disable() - disable local port ntb link (NTB API callback)
948 dev_dbg(&ndev->ntb.pdev->dev, "Local NTB link disabled"); in idt_ntb_link_disable()
956 * IDT PCIe-switches have two types of memory windows: MWs with direct
959 * of specified target port. So it implemets just ont-to-one mapping. Lookup
960 * table in its turn can map one BAR address space to up to 24 different
962 * NT-functions BARs can be turned on to implement either direct or lookup
963 * table based address translations, so:
964 * BAR0 - NT configuration registers space/direct address translation
965 * BAR1 - direct address translation/upper address of BAR0x64
966 * BAR2 - direct address translation/Lookup table with either 12 or 24 entries
967 * BAR3 - direct address translation/upper address of BAR2x64
968 * BAR4 - direct address translation/Lookup table with either 12 or 24 entries
969 * BAR5 - direct address translation/upper address of BAR4x64
970 * Additionally BAR2 and BAR4 can't have 24-entries LUT enabled at the same
975 * NOTE 1 BAR setup must be done before Linux kernel enumerated NT-function
978 * or using EEPROM connected to IDT PCIe-switch master SMBus.
980 * NOTE 2 This driver expects BAR0 mapping NT-function configuration space.
982 * per each NT-function if all the BARs are of 32bit type.
987 * idt_get_mw_count() - get memory window count
1009 * idt_get_mw_name() - get memory window name
1031 * idt_scan_mws() - scan memory windows of the port
1034 * @mw_cnt: Out - number of memory windows
1086 return ERR_PTR(-EINVAL); in idt_scan_mws()
1107 ret_mws = devm_kcalloc(&ndev->ntb.pdev->dev, *mw_cnt, sizeof(*ret_mws), in idt_scan_mws()
1110 return ERR_PTR(-ENOMEM); in idt_scan_mws()
1119 * idt_init_mws() - initialize memory windows subsystem
1133 ndev->mws = idt_scan_mws(ndev, ndev->port, &ndev->mw_cnt); in idt_init_mws()
1134 if (IS_ERR(ndev->mws)) { in idt_init_mws()
1135 dev_err(&ndev->ntb.pdev->dev, in idt_init_mws()
1136 "Failed to scan mws of local port %hhu", ndev->port); in idt_init_mws()
1137 return PTR_ERR(ndev->mws); in idt_init_mws()
1141 for (pidx = 0; pidx < ndev->peer_cnt; pidx++) { in idt_init_mws()
1142 peer = &ndev->peers[pidx]; in idt_init_mws()
1143 peer->mws = idt_scan_mws(ndev, peer->port, &peer->mw_cnt); in idt_init_mws()
1144 if (IS_ERR(peer->mws)) { in idt_init_mws()
1145 dev_err(&ndev->ntb.pdev->dev, in idt_init_mws()
1146 "Failed to scan mws of port %hhu", peer->port); in idt_init_mws()
1147 return PTR_ERR(peer->mws); in idt_init_mws()
1152 spin_lock_init(&ndev->lut_lock); in idt_init_mws()
1154 dev_dbg(&ndev->ntb.pdev->dev, "Outbound and inbound MWs initialized"); in idt_init_mws()
1160 * idt_ntb_mw_count() - number of inbound memory windows (NTB API callback)
1165 * be different for different port depending on the IDT PCIe-switch
1174 if (pidx < 0 || ndev->peer_cnt <= pidx) in idt_ntb_mw_count()
1175 return -EINVAL; in idt_ntb_mw_count()
1177 return ndev->peers[pidx].mw_cnt; in idt_ntb_mw_count()
1181 * idt_ntb_mw_get_align() - inbound memory window parameters (NTB API callback)
1185 * @addr_align: OUT - the base alignment for translating the memory window
1186 * @size_align: OUT - the size alignment for translating the memory window
1187 * @size_max: OUT - the maximum size of the memory window
1202 if (pidx < 0 || ndev->peer_cnt <= pidx) in idt_ntb_mw_get_align()
1203 return -EINVAL; in idt_ntb_mw_get_align()
1205 peer = &ndev->peers[pidx]; in idt_ntb_mw_get_align()
1207 if (widx < 0 || peer->mw_cnt <= widx) in idt_ntb_mw_get_align()
1208 return -EINVAL; in idt_ntb_mw_get_align()
1211 *addr_align = peer->mws[widx].addr_align; in idt_ntb_mw_get_align()
1214 *size_align = peer->mws[widx].size_align; in idt_ntb_mw_get_align()
1217 *size_max = peer->mws[widx].size_max; in idt_ntb_mw_get_align()
1223 * idt_ntb_peer_mw_count() - number of outbound memory windows
1236 return ndev->mw_cnt; in idt_ntb_peer_mw_count()
1240 * idt_ntb_peer_mw_get_addr() - get map address of an outbound memory window
1244 * @base: OUT - the base address of mapping region.
1245 * @size: OUT - the size of mapping region.
1257 if (widx < 0 || ndev->mw_cnt <= widx) in idt_ntb_peer_mw_get_addr()
1258 return -EINVAL; in idt_ntb_peer_mw_get_addr()
1262 *base = pci_resource_start(ntb->pdev, ndev->mws[widx].bar) + in idt_ntb_peer_mw_get_addr()
1263 ndev->mws[widx].idx * ndev->mws[widx].size_max; in idt_ntb_peer_mw_get_addr()
1267 *size = ndev->mws[widx].size_max; in idt_ntb_peer_mw_get_addr()
1273 * idt_ntb_peer_mw_set_trans() - set a translation address of a memory window
1294 if (pidx < 0 || ndev->peer_cnt <= pidx) in idt_ntb_peer_mw_set_trans()
1295 return -EINVAL; in idt_ntb_peer_mw_set_trans()
1297 if (widx < 0 || ndev->mw_cnt <= widx) in idt_ntb_peer_mw_set_trans()
1298 return -EINVAL; in idt_ntb_peer_mw_set_trans()
1304 mw_cfg = &ndev->mws[widx]; in idt_ntb_peer_mw_set_trans()
1305 if (!IS_ALIGNED(addr, mw_cfg->addr_align)) in idt_ntb_peer_mw_set_trans()
1306 return -EINVAL; in idt_ntb_peer_mw_set_trans()
1307 if (!IS_ALIGNED(size, mw_cfg->size_align) || size > mw_cfg->size_max) in idt_ntb_peer_mw_set_trans()
1308 return -EINVAL; in idt_ntb_peer_mw_set_trans()
1311 if (mw_cfg->type == IDT_MW_DIR) { in idt_ntb_peer_mw_set_trans()
1312 const struct idt_ntb_bar *bar = &ntdata_tbl.bars[mw_cfg->bar]; in idt_ntb_peer_mw_set_trans()
1315 data = idt_nt_read(ndev, bar->setup); in idt_ntb_peer_mw_set_trans()
1316 data = SET_FIELD(BARSETUP_TPART, data, ndev->peers[pidx].part); in idt_ntb_peer_mw_set_trans()
1317 idt_nt_write(ndev, bar->setup, data); in idt_ntb_peer_mw_set_trans()
1319 idt_nt_write(ndev, bar->ltbase, (u32)addr); in idt_ntb_peer_mw_set_trans()
1320 idt_nt_write(ndev, bar->utbase, (u32)(addr >> 32)); in idt_ntb_peer_mw_set_trans()
1322 limit = pci_bus_address(ntb->pdev, mw_cfg->bar) + size; in idt_ntb_peer_mw_set_trans()
1323 idt_nt_write(ndev, bar->limit, (u32)limit); in idt_ntb_peer_mw_set_trans()
1325 idt_nt_write(ndev, (bar + 1)->limit, (limit >> 32)); in idt_ntb_peer_mw_set_trans()
1329 lutoff = SET_FIELD(LUTOFFSET_INDEX, 0, mw_cfg->idx) | in idt_ntb_peer_mw_set_trans()
1330 SET_FIELD(LUTOFFSET_BAR, 0, mw_cfg->bar); in idt_ntb_peer_mw_set_trans()
1331 data = SET_FIELD(LUTUDATA_PART, 0, ndev->peers[pidx].part) | in idt_ntb_peer_mw_set_trans()
1333 spin_lock_irqsave(&ndev->lut_lock, irqflags); in idt_ntb_peer_mw_set_trans()
1338 spin_unlock_irqrestore(&ndev->lut_lock, irqflags); in idt_ntb_peer_mw_set_trans()
1346 * idt_ntb_peer_mw_clear_trans() - clear the outbound MW translation address
1362 if (pidx < 0 || ndev->peer_cnt <= pidx) in idt_ntb_peer_mw_clear_trans()
1363 return -EINVAL; in idt_ntb_peer_mw_clear_trans()
1365 if (widx < 0 || ndev->mw_cnt <= widx) in idt_ntb_peer_mw_clear_trans()
1366 return -EINVAL; in idt_ntb_peer_mw_clear_trans()
1368 mw_cfg = &ndev->mws[widx]; in idt_ntb_peer_mw_clear_trans()
1371 if (mw_cfg->type == IDT_MW_DIR) { in idt_ntb_peer_mw_clear_trans()
1372 const struct idt_ntb_bar *bar = &ntdata_tbl.bars[mw_cfg->bar]; in idt_ntb_peer_mw_clear_trans()
1375 data = idt_nt_read(ndev, bar->setup); in idt_ntb_peer_mw_clear_trans()
1377 idt_nt_write(ndev, bar->limit, 0); in idt_ntb_peer_mw_clear_trans()
1379 idt_nt_write(ndev, (bar + 1)->limit, 0); in idt_ntb_peer_mw_clear_trans()
1384 lutoff = SET_FIELD(LUTOFFSET_INDEX, 0, mw_cfg->idx) | in idt_ntb_peer_mw_clear_trans()
1385 SET_FIELD(LUTOFFSET_BAR, 0, mw_cfg->bar); in idt_ntb_peer_mw_clear_trans()
1386 spin_lock_irqsave(&ndev->lut_lock, irqflags); in idt_ntb_peer_mw_clear_trans()
1391 spin_unlock_irqrestore(&ndev->lut_lock, irqflags); in idt_ntb_peer_mw_clear_trans()
1400 * Doorbell functionality of IDT PCIe-switches is pretty unusual. First of
1402 * NT-function of the IDT device in accordance with global permissions. These
1405 * doorbell is reflected to the NT-functions local inbound doorbell registers.
1409 * Secondly there is just one IRQ vector for Doorbell, Message, Temperature
1417 * idt_db_isr() - doorbell event ISR
1419 * @ntint_sts: NT-function interrupt status
1424 * The method is called from PCIe ISR bottom-half routine.
1432 dev_dbg(&ndev->ntb.pdev->dev, "DB IRQ detected %#08x", ntint_sts); in idt_db_isr()
1435 ntb_db_event(&ndev->ntb, 0); in idt_db_isr()
1439 * idt_ntb_db_valid_mask() - get a mask of doorbell bits supported by the ntb
1443 * IDT PCIe-switches expose just one Doorbell register of DWORD size.
1453 * idt_ntb_db_read() - read the local doorbell register (NTB API callback)
1456 * There is just on inbound doorbell register of each NT-function, so
1469 * idt_ntb_db_clear() - clear bits in the local doorbell register
1491 * idt_ntb_db_read_mask() - read the local doorbell mask (NTB API callback)
1508 * idt_ntb_db_set_mask() - set bits in the local doorbell mask
1522 return idt_reg_set_bits(ndev, IDT_NT_INDBELLMSK, &ndev->db_mask_lock, in idt_ntb_db_set_mask()
1527 * idt_ntb_db_clear_mask() - clear bits in the local doorbell mask
1533 * bitfield. IDT PCIe-switch shall generate an interrupt if there hasn't
1543 idt_reg_clear_bits(ndev, IDT_NT_INDBELLMSK, &ndev->db_mask_lock, in idt_ntb_db_clear_mask()
1550 * idt_ntb_peer_db_set() - set bits in the peer doorbell register
1555 * IDT PCIe-switches exposes local outbound doorbell register to change peer
1565 return -EINVAL; in idt_ntb_peer_db_set()
1574 * Each NT-function of IDT PCIe-switch has four inbound and four outbound
1577 * configurations. Since NTB API permits one-on-one message registers mapping
1583 * idt_init_msg() - initialize messaging interface
1592 /* Init the messages routing table lockers */ in idt_init_msg()
1594 spin_lock_init(&ndev->msg_locks[midx]); in idt_init_msg()
1596 dev_dbg(&ndev->ntb.pdev->dev, "NTB Messaging initialized"); in idt_init_msg()
1600 * idt_msg_isr() - message event ISR
1602 * @ntint_sts: NT-function interrupt status
1607 * The method is called from PCIe ISR bottom-half routine.
1615 dev_dbg(&ndev->ntb.pdev->dev, "Message IRQ detected %#08x", ntint_sts); in idt_msg_isr()
1618 ntb_msg_event(&ndev->ntb); in idt_msg_isr()
1622 * idt_ntb_msg_count() - get the number of message registers (NTB API callback)
1625 * IDT PCIe-switches support four message registers.
1635 * idt_ntb_msg_inbits() - get a bitfield of inbound message registers status
1650 * idt_ntb_msg_outbits() - get a bitfield of outbound message registers status
1665 * idt_ntb_msg_read_sts() - read the message registers status (NTB API callback)
1668 * IDT PCIe-switches expose message status registers to notify drivers of
1681 * idt_ntb_msg_clear_sts() - clear status bits of message registers
1703 * idt_ntb_msg_set_mask() - set mask of message register status bits
1716 return idt_reg_set_bits(ndev, IDT_NT_MSGSTSMSK, &ndev->msg_mask_lock, in idt_ntb_msg_set_mask()
1721 * idt_ntb_msg_clear_mask() - clear message registers mask
1734 idt_reg_clear_bits(ndev, IDT_NT_MSGSTSMSK, &ndev->msg_mask_lock, in idt_ntb_msg_clear_mask()
1741 * idt_ntb_msg_read() - read message register with specified index
1744 * @pidx: OUT - Port index of peer device a message retrieved from
1763 *pidx = ndev->part_idx_map[srcpart]; in idt_ntb_msg_read()
1766 if (*pidx == -EINVAL) in idt_ntb_msg_read()
1775 * idt_ntb_peer_msg_write() - write data to the specified message register
1795 return -EINVAL; in idt_ntb_peer_msg_write()
1797 if (pidx < 0 || ndev->peer_cnt <= pidx) in idt_ntb_peer_msg_write()
1798 return -EINVAL; in idt_ntb_peer_msg_write()
1802 SET_FIELD(SWPxMSGCTL_PART, 0, ndev->peers[pidx].part); in idt_ntb_peer_msg_write()
1804 /* Lock the messages routing table of the specified register */ in idt_ntb_peer_msg_write()
1805 spin_lock_irqsave(&ndev->msg_locks[midx], irqflags); in idt_ntb_peer_msg_write()
1807 idt_sw_write(ndev, partdata_tbl[ndev->part].msgctl[midx], swpmsgctl); in idt_ntb_peer_msg_write()
1809 /* Unlock the messages routing table */ in idt_ntb_peer_msg_write()
1810 spin_unlock_irqrestore(&ndev->msg_locks[midx], irqflags); in idt_ntb_peer_msg_write()
1817 * 7. Temperature sensor operations
1819 * IDT PCIe-switch has an embedded temperature sensor, which can be used to
1820 * check current chip core temperature. Since a workload environment can be
1829 * idt_get_deg() - convert millidegree Celsius value to just degree
1830 * @mdegC: IN - millidegree Celsius value
1840 * idt_get_frac() - retrieve 0/0.5 fraction of the millidegree Celsius value
1841 * @mdegC: IN - millidegree Celsius value
1851 * idt_get_temp_fmt() - convert millidegree Celsius value to 0:7:1 format
1852 * @mdegC: IN - millidegree Celsius value
1854 * Return: 0:7:1 format acceptable by the IDT temperature sensor
1862 * idt_get_temp_sval() - convert temp sample to signed millidegree Celsius
1863 * @data: IN - shifted to LSB 8-bits temperature sample
1873 * idt_get_temp_sval() - convert temp sample to unsigned millidegree Celsius
1874 * @data: IN - shifted to LSB 8-bits temperature sample
1884 * idt_read_temp() - read temperature from chip sensor
1886 * @type: IN - type of the temperature value to read
1887 * @val: OUT - integer value of temperature in millidegree Celsius
1894 /* Alter the temperature field in accordance with the passed type */ in idt_read_temp()
1925 * idt_write_temp() - write temperature to the chip sensor register
1927 * @type: IN - type of the temperature value to change
1928 * @val: IN - integer value of temperature in millidegree Celsius
1937 /* Retrieve the properly formatted temperature value */ in idt_write_temp()
1940 mutex_lock(&ndev->hwmon_mtx); in idt_write_temp()
1963 mutex_unlock(&ndev->hwmon_mtx); in idt_write_temp()
1967 * idt_sysfs_show_temp() - printout corresponding temperature value
1970 * @buf: Buffer to print temperature out
1979 enum idt_temp_val type = attr->index; in idt_sysfs_show_temp()
1987 * idt_sysfs_set_temp() - set corresponding temperature value
1990 * @buf: Buffer to print temperature out
2001 enum idt_temp_val type = attr->index; in idt_sysfs_set_temp()
2022 * idt_sysfs_reset_hist() - reset temperature history
2025 * @buf: Buffer to print temperature out
2036 /* Just set the maximal value to the lowest temperature field and in idt_sysfs_reset_hist()
2037 * minimal value to the highest temperature field in idt_sysfs_reset_hist()
2072 * idt_init_temp() - initialize temperature sensor interface
2088 mutex_init(&ndev->hwmon_mtx); in idt_init_temp()
2090 hwmon = devm_hwmon_device_register_with_groups(&ndev->ntb.pdev->dev, in idt_init_temp()
2091 ndev->swcfg->name, ndev, idt_temp_groups); in idt_init_temp()
2093 dev_err(&ndev->ntb.pdev->dev, "Couldn't create hwmon device"); in idt_init_temp()
2097 dev_dbg(&ndev->ntb.pdev->dev, "Temperature HWmon interface registered"); in idt_init_temp()
2103 * IDT PCIe-switch has strangely developed IRQ system. There is just one
2107 * switch or temperature sensor events pop up. The difference is that SEVENT
2111 * The hardware driver has only bottom-half handler of the IRQ, since if any
2120 * idt_init_isr() - initialize PCIe interrupt handler
2127 struct pci_dev *pdev = ndev->ntb.pdev; in idt_init_isr()
2134 dev_err(&pdev->dev, "Failed to allocate IRQ vector"); in idt_init_isr()
2141 dev_err(&pdev->dev, "Failed to get IRQ vector"); in idt_init_isr()
2146 ret = devm_request_threaded_irq(&pdev->dev, ret, NULL, idt_thread_isr, in idt_init_isr()
2149 dev_err(&pdev->dev, "Failed to set MSI IRQ handler, %d", ret); in idt_init_isr()
2158 dev_dbg(&pdev->dev, "NTB interrupts initialized"); in idt_init_isr()
2169 * idt_deinit_ist() - deinitialize PCIe interrupt handler
2176 struct pci_dev *pdev = ndev->ntb.pdev; in idt_deinit_isr()
2184 devm_free_irq(&pdev->dev, pci_irq_vector(pdev, 0), ndev); in idt_deinit_isr()
2189 dev_dbg(&pdev->dev, "NTB interrupts deinitialized"); in idt_deinit_isr()
2193 * idt_thread_isr() - NT function interrupts handler
2199 * The method is bottom-half routine of actual default PCIe IRQ handler.
2228 dev_dbg(&ndev->ntb.pdev->dev, "IDT IRQs 0x%08x handled", ntint_sts); in idt_thread_isr()
2274 * idt_register_device() - register IDT NTB device
2284 ndev->ntb.ops = &idt_ntb_ops; in idt_register_device()
2285 ndev->ntb.topo = NTB_TOPO_SWITCH; in idt_register_device()
2287 ret = ntb_register_device(&ndev->ntb); in idt_register_device()
2289 dev_err(&ndev->ntb.pdev->dev, "Failed to register NTB device"); in idt_register_device()
2293 dev_dbg(&ndev->ntb.pdev->dev, "NTB device successfully registered"); in idt_register_device()
2299 * idt_unregister_device() - unregister IDT NTB device
2305 ntb_unregister_device(&ndev->ntb); in idt_unregister_device()
2307 dev_dbg(&ndev->ntb.pdev->dev, "NTB device unregistered"); in idt_unregister_device()
2328 * idt_dbgfs_info_read() - DebugFS read info node callback
2330 * @ubuf: User-space buffer to put data to
2337 struct idt_ntb_dev *ndev = filp->private_data; in idt_dbgfs_info_read()
2353 return -ENOMEM; in idt_dbgfs_info_read()
2356 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2360 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2361 "Local Port %hhu, Partition %hhu\n", ndev->port, ndev->part); in idt_dbgfs_info_read()
2364 off += scnprintf(strbuf + off, size - off, "Peers:\n"); in idt_dbgfs_info_read()
2365 for (idx = 0; idx < ndev->peer_cnt; idx++) { in idt_dbgfs_info_read()
2366 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2368 idx, ndev->peers[idx].port, ndev->peers[idx].part); in idt_dbgfs_info_read()
2372 data = idt_ntb_link_is_up(&ndev->ntb, &speed, &width); in idt_dbgfs_info_read()
2373 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2374 "NTB link status\t- 0x%08x, ", data); in idt_dbgfs_info_read()
2375 off += scnprintf(strbuf + off, size - off, "PCIe Gen %d x%d lanes\n", in idt_dbgfs_info_read()
2378 /* Mapping table entries */ in idt_dbgfs_info_read()
2379 off += scnprintf(strbuf + off, size - off, "NTB Mapping Table:\n"); in idt_dbgfs_info_read()
2381 spin_lock_irqsave(&ndev->mtbl_lock, irqflags); in idt_dbgfs_info_read()
2384 spin_unlock_irqrestore(&ndev->mtbl_lock, irqflags); in idt_dbgfs_info_read()
2388 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2394 off += scnprintf(strbuf + off, size - off, "\n"); in idt_dbgfs_info_read()
2397 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2399 for (idx = 0; idx < ndev->mw_cnt; idx += cnt) { in idt_dbgfs_info_read()
2400 data = ndev->mws[idx].type; in idt_dbgfs_info_read()
2405 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2408 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2409 "\t%hhu-%d.\t", idx, idx + cnt - 1); in idt_dbgfs_info_read()
2411 off += scnprintf(strbuf + off, size - off, "%s BAR%hhu, ", in idt_dbgfs_info_read()
2412 idt_get_mw_name(data), ndev->mws[idx].bar); in idt_dbgfs_info_read()
2414 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2415 "Address align 0x%08llx, ", ndev->mws[idx].addr_align); in idt_dbgfs_info_read()
2417 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2419 ndev->mws[idx].size_align, ndev->mws[idx].size_max); in idt_dbgfs_info_read()
2423 for (pidx = 0; pidx < ndev->peer_cnt; pidx++) { in idt_dbgfs_info_read()
2424 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2426 pidx, ndev->peers[pidx].port); in idt_dbgfs_info_read()
2429 for (idx = 0; idx < ndev->peers[pidx].mw_cnt; idx += cnt) { in idt_dbgfs_info_read()
2430 data = ndev->peers[pidx].mws[idx].type; in idt_dbgfs_info_read()
2434 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2437 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2438 "\t%hhu-%d.\t", idx, idx + cnt - 1); in idt_dbgfs_info_read()
2440 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2442 ndev->peers[pidx].mws[idx].bar); in idt_dbgfs_info_read()
2444 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2446 ndev->peers[pidx].mws[idx].addr_align); in idt_dbgfs_info_read()
2448 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2450 ndev->peers[pidx].mws[idx].size_align, in idt_dbgfs_info_read()
2451 ndev->peers[pidx].mws[idx].size_max); in idt_dbgfs_info_read()
2454 off += scnprintf(strbuf + off, size - off, "\n"); in idt_dbgfs_info_read()
2458 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2459 "Global Doorbell state\t- 0x%08x\n", data); in idt_dbgfs_info_read()
2460 data = idt_ntb_db_read(&ndev->ntb); in idt_dbgfs_info_read()
2461 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2462 "Local Doorbell state\t- 0x%08x\n", data); in idt_dbgfs_info_read()
2464 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2465 "Local Doorbell mask\t- 0x%08x\n", data); in idt_dbgfs_info_read()
2466 off += scnprintf(strbuf + off, size - off, "\n"); in idt_dbgfs_info_read()
2469 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2470 "Message event valid\t- 0x%08x\n", IDT_MSG_MASK); in idt_dbgfs_info_read()
2471 data = idt_ntb_msg_read_sts(&ndev->ntb); in idt_dbgfs_info_read()
2472 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2473 "Message event status\t- 0x%08x\n", data); in idt_dbgfs_info_read()
2475 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2476 "Message event mask\t- 0x%08x\n", data); in idt_dbgfs_info_read()
2477 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2481 data = idt_ntb_msg_read(&ndev->ntb, &src, idx); in idt_dbgfs_info_read()
2482 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2484 idx, data, src, ndev->peers[src].port); in idt_dbgfs_info_read()
2486 off += scnprintf(strbuf + off, size - off, "\n"); in idt_dbgfs_info_read()
2488 /* Current temperature */ in idt_dbgfs_info_read()
2490 off += scnprintf(strbuf + off, size - off, in idt_dbgfs_info_read()
2491 "Switch temperature\t\t- %hhd.%hhuC\n", in idt_dbgfs_info_read()
2502 * idt_init_dbgfs() - initialize DebugFS node
2513 dev_info(&ndev->ntb.pdev->dev, "Top DebugFS directory absent"); in idt_init_dbgfs()
2518 snprintf(devname, 64, "info:%s", pci_name(ndev->ntb.pdev)); in idt_init_dbgfs()
2519 ndev->dbgfs_info = debugfs_create_file(devname, 0400, dbgfs_topdir, in idt_init_dbgfs()
2521 if (IS_ERR(ndev->dbgfs_info)) { in idt_init_dbgfs()
2522 dev_dbg(&ndev->ntb.pdev->dev, "Failed to create DebugFS node"); in idt_init_dbgfs()
2523 return PTR_ERR(ndev->dbgfs_info); in idt_init_dbgfs()
2526 dev_dbg(&ndev->ntb.pdev->dev, "NTB device DebugFS node created"); in idt_init_dbgfs()
2532 * idt_deinit_dbgfs() - deinitialize DebugFS node
2539 debugfs_remove(ndev->dbgfs_info); in idt_deinit_dbgfs()
2541 dev_dbg(&ndev->ntb.pdev->dev, "NTB device DebugFS node discarded"); in idt_deinit_dbgfs()
2550 * idt_check_setup() - Check whether the IDT PCIe-swtich is properly
2551 * pre-initialized
2564 dev_err(&pdev->dev, in idt_check_setup()
2571 dev_err(&pdev->dev, "BAR0 doesn't map config space"); in idt_check_setup()
2572 return -EINVAL; in idt_check_setup()
2577 dev_err(&pdev->dev, "Invalid size of config space"); in idt_check_setup()
2578 return -EINVAL; in idt_check_setup()
2581 dev_dbg(&pdev->dev, "NTB device pre-initialized correctly"); in idt_check_setup()
2587 * Create the IDT PCIe-switch driver descriptor
2589 * @id: IDT PCIe-device configuration
2591 * It just allocates a memory for IDT PCIe-switch device structure and
2604 /* Allocate memory for the IDT PCIe-device descriptor */ in idt_create_dev()
2605 ndev = devm_kzalloc(&pdev->dev, sizeof(*ndev), GFP_KERNEL); in idt_create_dev()
2607 dev_err(&pdev->dev, "Memory allocation failed for descriptor"); in idt_create_dev()
2608 return ERR_PTR(-ENOMEM); in idt_create_dev()
2611 /* Save the IDT PCIe-switch ports configuration */ in idt_create_dev()
2612 ndev->swcfg = (struct idt_89hpes_cfg *)id->driver_data; in idt_create_dev()
2613 /* Save the PCI-device pointer inside the NTB device structure */ in idt_create_dev()
2614 ndev->ntb.pdev = pdev; in idt_create_dev()
2617 spin_lock_init(&ndev->db_mask_lock); in idt_create_dev()
2618 spin_lock_init(&ndev->msg_mask_lock); in idt_create_dev()
2619 spin_lock_init(&ndev->gasa_lock); in idt_create_dev()
2621 dev_info(&pdev->dev, "IDT %s discovered", ndev->swcfg->name); in idt_create_dev()
2623 dev_dbg(&pdev->dev, "NTB device descriptor created"); in idt_create_dev()
2629 * idt_init_pci() - initialize the basic PCI-related subsystem
2630 * @ndev: Pointer to the IDT PCIe-switch driver descriptor
2639 struct pci_dev *pdev = ndev->ntb.pdev; in idt_init_pci()
2643 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); in idt_init_pci()
2645 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); in idt_init_pci()
2647 dev_err(&pdev->dev, "Failed to set DMA bit mask\n"); in idt_init_pci()
2650 dev_warn(&pdev->dev, "Cannot set DMA highmem bit mask\n"); in idt_init_pci()
2664 dev_err(&pdev->dev, "Failed to enable PCIe device\n"); in idt_init_pci()
2677 dev_err(&pdev->dev, "Failed to request resources\n"); in idt_init_pci()
2681 /* Retrieve virtual address of BAR0 - PCI configuration space */ in idt_init_pci()
2682 ndev->cfgspc = pcim_iomap_table(pdev)[0]; in idt_init_pci()
2684 /* Put the IDT driver data pointer to the PCI-device private pointer */ in idt_init_pci()
2687 dev_dbg(&pdev->dev, "NT-function PCIe interface initialized"); in idt_init_pci()
2698 * idt_deinit_pci() - deinitialize the basic PCI-related subsystem
2699 * @ndev: Pointer to the IDT PCIe-switch driver descriptor
2705 struct pci_dev *pdev = ndev->ntb.pdev; in idt_deinit_pci()
2707 /* Clean up the PCI-device private data pointer */ in idt_deinit_pci()
2713 dev_dbg(&pdev->dev, "NT-function PCIe interface cleared"); in idt_deinit_pci()
2722 * idt_pci_probe() - PCI device probe callback
2734 /* Check whether IDT PCIe-switch is properly pre-initialized */ in idt_pci_probe()
2749 /* Scan ports of the IDT PCIe-switch */ in idt_pci_probe()
2779 /* IDT PCIe-switch NTB driver is finally initialized */ in idt_pci_probe()
2780 dev_info(&pdev->dev, "IDT NTB device is ready"); in idt_pci_probe()
2795 * idt_pci_probe() - PCI device remove callback
2817 /* IDT PCIe-switch NTB driver is finally initialized */ in idt_pci_remove()
2818 dev_info(&pdev->dev, "IDT NTB device is removed"); in idt_pci_remove()
2824 * IDT PCIe-switch models ports configuration structures
2860 * PCI-ids table of the supported IDT PCIe-switch devices
2876 * IDT PCIe-switch NT-function device driver structure definition