162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2007 PA Semi, Inc 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Parts based on arch/powerpc/sysdev/fsl_soc.c: 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * 2006 (c) MontaVista Software, Inc. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/errno.h> 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/pci.h> 1362306a36Sopenharmony_ci#include <linux/of.h> 1462306a36Sopenharmony_ci#include <linux/of_irq.h> 1562306a36Sopenharmony_ci#include <linux/i2c.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#ifdef CONFIG_I2C_BOARDINFO 1862306a36Sopenharmony_ci/* The below is from fsl_soc.c. It's copied because since there are no 1962306a36Sopenharmony_ci * official bus bindings at this time it doesn't make sense to share across 2062306a36Sopenharmony_ci * the platforms, even though they happen to be common. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_cistruct i2c_driver_device { 2362306a36Sopenharmony_ci char *of_device; 2462306a36Sopenharmony_ci char *i2c_type; 2562306a36Sopenharmony_ci}; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic struct i2c_driver_device i2c_devices[] __initdata = { 2862306a36Sopenharmony_ci {"dallas,ds1338", "ds1338"}, 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic int __init find_i2c_driver(struct device_node *node, 3262306a36Sopenharmony_ci struct i2c_board_info *info) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci int i; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) { 3762306a36Sopenharmony_ci if (!of_device_is_compatible(node, i2c_devices[i].of_device)) 3862306a36Sopenharmony_ci continue; 3962306a36Sopenharmony_ci if (strscpy(info->type, i2c_devices[i].i2c_type, I2C_NAME_SIZE) < 0) 4062306a36Sopenharmony_ci return -ENOMEM; 4162306a36Sopenharmony_ci return 0; 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci return -ENODEV; 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic int __init pasemi_register_i2c_devices(void) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci struct pci_dev *pdev; 4962306a36Sopenharmony_ci struct device_node *adap_node; 5062306a36Sopenharmony_ci struct device_node *node; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci pdev = NULL; 5362306a36Sopenharmony_ci while ((pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa003, pdev))) { 5462306a36Sopenharmony_ci adap_node = pci_device_to_OF_node(pdev); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if (!adap_node) 5762306a36Sopenharmony_ci continue; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci for_each_child_of_node(adap_node, node) { 6062306a36Sopenharmony_ci struct i2c_board_info info = {}; 6162306a36Sopenharmony_ci const u32 *addr; 6262306a36Sopenharmony_ci int len; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci addr = of_get_property(node, "reg", &len); 6562306a36Sopenharmony_ci if (!addr || len < sizeof(int) || 6662306a36Sopenharmony_ci *addr > (1 << 10) - 1) { 6762306a36Sopenharmony_ci pr_warn("pasemi_register_i2c_devices: invalid i2c device entry\n"); 6862306a36Sopenharmony_ci continue; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci info.irq = irq_of_parse_and_map(node, 0); 7262306a36Sopenharmony_ci if (!info.irq) 7362306a36Sopenharmony_ci info.irq = -1; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci if (find_i2c_driver(node, &info) < 0) 7662306a36Sopenharmony_ci continue; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci info.addr = *addr; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci i2c_register_board_info(PCI_FUNC(pdev->devfn), &info, 8162306a36Sopenharmony_ci 1); 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_cidevice_initcall(pasemi_register_i2c_devices); 8762306a36Sopenharmony_ci#endif 88