1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 2007 PA Semi, Inc |
4 | * |
5 | * Parts based on arch/powerpc/sysdev/fsl_soc.c: |
6 | * |
7 | * 2006 (c) MontaVista Software, Inc. |
8 | */ |
9 | |
10 | #include <linux/errno.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/pci.h> |
13 | #include <linux/of.h> |
14 | #include <linux/of_irq.h> |
15 | #include <linux/i2c.h> |
16 | |
17 | #ifdef CONFIG_I2C_BOARDINFO |
18 | /* The below is from fsl_soc.c. It's copied because since there are no |
19 | * official bus bindings at this time it doesn't make sense to share across |
20 | * the platforms, even though they happen to be common. |
21 | */ |
22 | struct i2c_driver_device { |
23 | char *of_device; |
24 | char *i2c_type; |
25 | }; |
26 | |
27 | static struct i2c_driver_device i2c_devices[] __initdata = { |
28 | {"dallas,ds1338" , "ds1338" }, |
29 | }; |
30 | |
31 | static int __init find_i2c_driver(struct device_node *node, |
32 | struct i2c_board_info *info) |
33 | { |
34 | int i; |
35 | |
36 | for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) { |
37 | if (!of_device_is_compatible(device: node, i2c_devices[i].of_device)) |
38 | continue; |
39 | if (strscpy(info->type, i2c_devices[i].i2c_type, I2C_NAME_SIZE) < 0) |
40 | return -ENOMEM; |
41 | return 0; |
42 | } |
43 | return -ENODEV; |
44 | } |
45 | |
46 | static int __init pasemi_register_i2c_devices(void) |
47 | { |
48 | struct pci_dev *pdev; |
49 | struct device_node *adap_node; |
50 | struct device_node *node; |
51 | |
52 | pdev = NULL; |
53 | while ((pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, device: 0xa003, from: pdev))) { |
54 | adap_node = pci_device_to_OF_node(pdev); |
55 | |
56 | if (!adap_node) |
57 | continue; |
58 | |
59 | for_each_child_of_node(adap_node, node) { |
60 | struct i2c_board_info info = {}; |
61 | const u32 *addr; |
62 | int len; |
63 | |
64 | addr = of_get_property(node, name: "reg" , lenp: &len); |
65 | if (!addr || len < sizeof(int) || |
66 | *addr > (1 << 10) - 1) { |
67 | pr_warn("pasemi_register_i2c_devices: invalid i2c device entry\n" ); |
68 | continue; |
69 | } |
70 | |
71 | info.irq = irq_of_parse_and_map(node, index: 0); |
72 | if (!info.irq) |
73 | info.irq = -1; |
74 | |
75 | if (find_i2c_driver(node, info: &info) < 0) |
76 | continue; |
77 | |
78 | info.addr = *addr; |
79 | |
80 | i2c_register_board_info(PCI_FUNC(pdev->devfn), info: &info, |
81 | n: 1); |
82 | } |
83 | } |
84 | return 0; |
85 | } |
86 | device_initcall(pasemi_register_i2c_devices); |
87 | #endif |
88 | |