Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spmi: pmic-arb: Add multi bus support

Starting with HW version 7, there are actually two separate buses
(with two separate sets of wires). So add support for the second bus.
The first platform that needs this support for the second bus is the
Qualcomm X1 Elite, so add the compatible for it as well.

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
Link: https://lore.kernel.org/r/20240417-spmi-multi-master-support-v10-7-5bc6d322e266@linaro.org
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Link: https://lore.kernel.org/r/20240507210809.3479953-13-sboyd@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Abel Vesa and committed by
Greg Kroah-Hartman
97998737 02922ccb

+120 -18
+120 -18
drivers/spmi/spmi-pmic-arb.c
··· 13 13 #include <linux/kernel.h> 14 14 #include <linux/module.h> 15 15 #include <linux/of.h> 16 + #include <linux/of_address.h> 16 17 #include <linux/of_irq.h> 17 18 #include <linux/platform_device.h> 18 19 #include <linux/slab.h> ··· 96 95 PMIC_ARB_CHANNEL_OBS, 97 96 }; 98 97 98 + #define PMIC_ARB_MAX_BUSES 2 99 + 99 100 /* Maximum number of support PMIC peripherals */ 100 101 #define PMIC_ARB_MAX_PERIPHS 512 101 102 #define PMIC_ARB_MAX_PERIPHS_V7 1024 ··· 152 149 * @min_apid: minimum APID (used for bounding IRQ search) 153 150 * @max_apid: maximum APID 154 151 * @irq: PMIC ARB interrupt. 152 + * @id: unique ID of the bus 155 153 */ 156 154 struct spmi_pmic_arb_bus { 157 155 struct spmi_pmic_arb *pmic_arb; ··· 171 167 u16 min_apid; 172 168 u16 max_apid; 173 169 int irq; 170 + u8 id; 174 171 }; 175 172 176 173 /** ··· 185 180 * @ee: the current Execution Environment 186 181 * @ver_ops: version dependent operations. 187 182 * @max_periphs: Number of elements in apid_data[] 188 - * @bus: per arbiter bus instance 183 + * @buses: per arbiter buses instances 184 + * @buses_available: number of buses registered 189 185 */ 190 186 struct spmi_pmic_arb { 191 187 void __iomem *rd_base; ··· 197 191 u8 ee; 198 192 const struct pmic_arb_ver_ops *ver_ops; 199 193 int max_periphs; 200 - struct spmi_pmic_arb_bus *bus; 194 + struct spmi_pmic_arb_bus *buses[PMIC_ARB_MAX_BUSES]; 195 + int buses_available; 201 196 }; 202 197 203 198 /** ··· 227 220 struct pmic_arb_ver_ops { 228 221 const char *ver_str; 229 222 int (*get_core_resources)(struct platform_device *pdev, void __iomem *core); 230 - int (*init_apid)(struct spmi_pmic_arb_bus *bus); 223 + int (*init_apid)(struct spmi_pmic_arb_bus *bus, int index); 231 224 int (*ppid_to_apid)(struct spmi_pmic_arb_bus *bus, u16 ppid); 232 225 /* spmi commands (read_cmd, write_cmd, cmd) functionality */ 233 226 int (*offset)(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr, ··· 316 309 } 317 310 318 311 if (status & PMIC_ARB_STATUS_FAILURE) { 319 - dev_err(&ctrl->dev, "%s: %#x %#x: transaction failed (%#x)\n", 320 - __func__, sid, addr, status); 312 + dev_err(&ctrl->dev, "%s: %#x %#x: transaction failed (%#x) reg: 0x%x\n", 313 + __func__, sid, addr, status, offset); 321 314 WARN_ON(1); 322 315 return -EIO; 323 316 } ··· 333 326 udelay(1); 334 327 } 335 328 336 - dev_err(&ctrl->dev, "%s: %#x %#x: timeout, status %#x\n", 337 - __func__, sid, addr, status); 329 + dev_err(&ctrl->dev, "%s: %#x %#x %#x: timeout, status %#x\n", 330 + __func__, bus->id, sid, addr, status); 338 331 return -ETIMEDOUT; 339 332 } 340 333 ··· 1010 1003 return 0; 1011 1004 } 1012 1005 1013 - static int pmic_arb_init_apid_v1(struct spmi_pmic_arb_bus *bus) 1006 + static int pmic_arb_init_apid_v1(struct spmi_pmic_arb_bus *bus, int index) 1014 1007 { 1015 1008 struct spmi_pmic_arb *pmic_arb = bus->pmic_arb; 1016 1009 u32 *mapping_table; 1010 + 1011 + if (index) { 1012 + dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n", 1013 + index); 1014 + return -EINVAL; 1015 + } 1017 1016 1018 1017 mapping_table = devm_kcalloc(&bus->spmic->dev, pmic_arb->max_periphs, 1019 1018 sizeof(*mapping_table), GFP_KERNEL); ··· 1263 1250 return 0x1000 * pmic_arb->ee + 0x8000 * apid; 1264 1251 } 1265 1252 1266 - static int pmic_arb_init_apid_v5(struct spmi_pmic_arb_bus *bus) 1253 + static int pmic_arb_init_apid_v5(struct spmi_pmic_arb_bus *bus, int index) 1267 1254 { 1268 1255 struct spmi_pmic_arb *pmic_arb = bus->pmic_arb; 1269 1256 int ret; 1257 + 1258 + if (index) { 1259 + dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n", 1260 + index); 1261 + return -EINVAL; 1262 + } 1270 1263 1271 1264 bus->base_apid = 0; 1272 1265 bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) & ··· 1343 1324 pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS_V7; 1344 1325 1345 1326 return pmic_arb_get_obsrvr_chnls_v2(pdev); 1327 + } 1328 + 1329 + /* 1330 + * Only v7 supports 2 buses. Each bus will get a different apid count, read 1331 + * from different registers. 1332 + */ 1333 + static int pmic_arb_init_apid_v7(struct spmi_pmic_arb_bus *bus, int index) 1334 + { 1335 + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb; 1336 + int ret; 1337 + 1338 + if (index == 0) { 1339 + bus->base_apid = 0; 1340 + bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) & 1341 + PMIC_ARB_FEATURES_PERIPH_MASK; 1342 + } else if (index == 1) { 1343 + bus->base_apid = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) & 1344 + PMIC_ARB_FEATURES_PERIPH_MASK; 1345 + bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES1) & 1346 + PMIC_ARB_FEATURES_PERIPH_MASK; 1347 + } else { 1348 + dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n", 1349 + bus->id); 1350 + return -EINVAL; 1351 + } 1352 + 1353 + if (bus->base_apid + bus->apid_count > pmic_arb->max_periphs) { 1354 + dev_err(&bus->spmic->dev, "Unsupported APID count %d detected\n", 1355 + bus->base_apid + bus->apid_count); 1356 + return -EINVAL; 1357 + } 1358 + 1359 + ret = pmic_arb_init_apid_min_max(bus); 1360 + if (ret) 1361 + return ret; 1362 + 1363 + ret = pmic_arb_read_apid_map_v5(bus); 1364 + if (ret) { 1365 + dev_err(&bus->spmic->dev, "could not read APID->PPID mapping table, rc= %d\n", 1366 + ret); 1367 + return ret; 1368 + } 1369 + 1370 + return 0; 1346 1371 } 1347 1372 1348 1373 /* ··· 1641 1578 static const struct pmic_arb_ver_ops pmic_arb_v7 = { 1642 1579 .ver_str = "v7", 1643 1580 .get_core_resources = pmic_arb_get_core_resources_v7, 1644 - .init_apid = pmic_arb_init_apid_v5, 1581 + .init_apid = pmic_arb_init_apid_v7, 1645 1582 .ppid_to_apid = pmic_arb_ppid_to_apid_v5, 1646 1583 .non_data_cmd = pmic_arb_non_data_cmd_v2, 1647 1584 .offset = pmic_arb_offset_v7, ··· 1665 1602 struct device_node *node, 1666 1603 struct spmi_pmic_arb *pmic_arb) 1667 1604 { 1605 + int bus_index = pmic_arb->buses_available; 1668 1606 struct spmi_pmic_arb_bus *bus; 1669 1607 struct device *dev = &pdev->dev; 1670 1608 struct spmi_controller *ctrl; ··· 1684 1620 1685 1621 bus = spmi_controller_get_drvdata(ctrl); 1686 1622 1687 - pmic_arb->bus = bus; 1623 + pmic_arb->buses[bus_index] = bus; 1688 1624 1689 1625 raw_spin_lock_init(&bus->lock); 1690 1626 ··· 1729 1665 bus->cnfg = cnfg; 1730 1666 bus->irq = irq; 1731 1667 bus->spmic = ctrl; 1668 + bus->id = bus_index; 1732 1669 1733 - ret = pmic_arb->ver_ops->init_apid(bus); 1670 + ret = pmic_arb->ver_ops->init_apid(bus, bus_index); 1734 1671 if (ret) 1735 1672 return ret; 1736 1673 1737 - dev_dbg(&pdev->dev, "adding irq domain\n"); 1674 + dev_dbg(&pdev->dev, "adding irq domain for bus %d\n", bus_index); 1738 1675 1739 1676 bus->domain = irq_domain_add_tree(dev->of_node, 1740 1677 &pmic_arb_irq_domain_ops, bus); ··· 1748 1683 pmic_arb_chained_irq, bus); 1749 1684 1750 1685 ctrl->dev.of_node = node; 1686 + dev_set_name(&ctrl->dev, "spmi-%d", bus_index); 1751 1687 1752 1688 ret = devm_spmi_controller_add(dev, ctrl); 1753 1689 if (ret) 1754 1690 return ret; 1755 1691 1692 + pmic_arb->buses_available++; 1693 + 1756 1694 return 0; 1695 + } 1696 + 1697 + static int spmi_pmic_arb_register_buses(struct spmi_pmic_arb *pmic_arb, 1698 + struct platform_device *pdev) 1699 + { 1700 + struct device *dev = &pdev->dev; 1701 + struct device_node *node = dev->of_node; 1702 + struct device_node *child; 1703 + int ret; 1704 + 1705 + /* legacy mode doesn't provide child node for the bus */ 1706 + if (of_device_is_compatible(node, "qcom,spmi-pmic-arb")) 1707 + return spmi_pmic_arb_bus_init(pdev, node, pmic_arb); 1708 + 1709 + for_each_available_child_of_node(node, child) { 1710 + if (of_node_name_eq(child, "spmi")) { 1711 + ret = spmi_pmic_arb_bus_init(pdev, child, pmic_arb); 1712 + if (ret) 1713 + return ret; 1714 + } 1715 + } 1716 + 1717 + return ret; 1718 + } 1719 + 1720 + static void spmi_pmic_arb_deregister_buses(struct spmi_pmic_arb *pmic_arb) 1721 + { 1722 + int i; 1723 + 1724 + for (i = 0; i < pmic_arb->buses_available; i++) { 1725 + struct spmi_pmic_arb_bus *bus = pmic_arb->buses[i]; 1726 + 1727 + irq_set_chained_handler_and_data(bus->irq, 1728 + NULL, NULL); 1729 + irq_domain_remove(bus->domain); 1730 + } 1757 1731 } 1758 1732 1759 1733 static int spmi_pmic_arb_probe(struct platform_device *pdev) ··· 1864 1760 1865 1761 pmic_arb->ee = ee; 1866 1762 1867 - return spmi_pmic_arb_bus_init(pdev, dev->of_node, pmic_arb); 1763 + return spmi_pmic_arb_register_buses(pmic_arb, pdev); 1868 1764 } 1869 1765 1870 1766 static void spmi_pmic_arb_remove(struct platform_device *pdev) 1871 1767 { 1872 1768 struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev); 1873 - struct spmi_pmic_arb_bus *bus = pmic_arb->bus; 1874 1769 1875 - irq_set_chained_handler_and_data(bus->irq, 1876 - NULL, NULL); 1877 - irq_domain_remove(bus->domain); 1770 + spmi_pmic_arb_deregister_buses(pmic_arb); 1878 1771 } 1879 1772 1880 1773 static const struct of_device_id spmi_pmic_arb_match_table[] = { 1881 1774 { .compatible = "qcom,spmi-pmic-arb", }, 1775 + { .compatible = "qcom,x1e80100-spmi-pmic-arb", }, 1882 1776 {}, 1883 1777 }; 1884 1778 MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table);