xref: /linux/drivers/gpu/drm/xe/xe_i2c.c (revision 0ea07b69517a16808ea700b3226ddfa4484f23b9)
1f0e53aadSHeikki Krogerus // SPDX-License-Identifier: GPL-2.0 OR MIT
2f0e53aadSHeikki Krogerus /*
3f0e53aadSHeikki Krogerus  * Intel Xe I2C attached Microcontroller Units (MCU)
4f0e53aadSHeikki Krogerus  *
5f0e53aadSHeikki Krogerus  * Copyright (C) 2025 Intel Corporation.
6f0e53aadSHeikki Krogerus  */
7f0e53aadSHeikki Krogerus 
8f0e53aadSHeikki Krogerus #include <linux/array_size.h>
9f0e53aadSHeikki Krogerus #include <linux/container_of.h>
10f0e53aadSHeikki Krogerus #include <linux/device.h>
11f0e53aadSHeikki Krogerus #include <linux/err.h>
12f0e53aadSHeikki Krogerus #include <linux/i2c.h>
13f0e53aadSHeikki Krogerus #include <linux/ioport.h>
14f0e53aadSHeikki Krogerus #include <linux/irq.h>
15f0e53aadSHeikki Krogerus #include <linux/irqdomain.h>
16f0e53aadSHeikki Krogerus #include <linux/notifier.h>
17f0e53aadSHeikki Krogerus #include <linux/pci.h>
18f0e53aadSHeikki Krogerus #include <linux/platform_device.h>
19f0e53aadSHeikki Krogerus #include <linux/property.h>
20f0e53aadSHeikki Krogerus #include <linux/regmap.h>
21f0e53aadSHeikki Krogerus #include <linux/sprintf.h>
22f0e53aadSHeikki Krogerus #include <linux/string.h>
23f0e53aadSHeikki Krogerus #include <linux/types.h>
24f0e53aadSHeikki Krogerus #include <linux/workqueue.h>
25f0e53aadSHeikki Krogerus 
26f0e53aadSHeikki Krogerus #include "regs/xe_i2c_regs.h"
27f0e53aadSHeikki Krogerus #include "regs/xe_irq_regs.h"
28f0e53aadSHeikki Krogerus 
29f0e53aadSHeikki Krogerus #include "xe_device.h"
30f0e53aadSHeikki Krogerus #include "xe_device_types.h"
31f0e53aadSHeikki Krogerus #include "xe_i2c.h"
32f0e53aadSHeikki Krogerus #include "xe_mmio.h"
33f0e53aadSHeikki Krogerus #include "xe_platform_types.h"
34f0e53aadSHeikki Krogerus 
35f0e53aadSHeikki Krogerus /**
36f0e53aadSHeikki Krogerus  * DOC: Xe I2C devices
37f0e53aadSHeikki Krogerus  *
38f0e53aadSHeikki Krogerus  * Register a platform device for the I2C host controller (Synpsys DesignWare
39f0e53aadSHeikki Krogerus  * I2C) if the registers of that controller are mapped to the MMIO, and also the
40f0e53aadSHeikki Krogerus  * I2C client device for the Add-In Management Controller (the MCU) attached to
41f0e53aadSHeikki Krogerus  * the host controller.
42f0e53aadSHeikki Krogerus  *
43f0e53aadSHeikki Krogerus  * See drivers/i2c/busses/i2c-designware-* for more information on the I2C host
44f0e53aadSHeikki Krogerus  * controller.
45f0e53aadSHeikki Krogerus  */
46f0e53aadSHeikki Krogerus 
47f0e53aadSHeikki Krogerus static const char adapter_name[] = "i2c_designware";
48f0e53aadSHeikki Krogerus 
49f0e53aadSHeikki Krogerus static const struct property_entry xe_i2c_adapter_properties[] = {
50f0e53aadSHeikki Krogerus 	PROPERTY_ENTRY_STRING("compatible", "intel,xe-i2c"),
51f0e53aadSHeikki Krogerus 	PROPERTY_ENTRY_U32("clock-frequency", I2C_MAX_FAST_MODE_PLUS_FREQ),
52f0e53aadSHeikki Krogerus 	{ }
53f0e53aadSHeikki Krogerus };
54f0e53aadSHeikki Krogerus 
55f0e53aadSHeikki Krogerus static inline void xe_i2c_read_endpoint(struct xe_mmio *mmio, void *ep)
56f0e53aadSHeikki Krogerus {
57f0e53aadSHeikki Krogerus 	u32 *val = ep;
58f0e53aadSHeikki Krogerus 
59f0e53aadSHeikki Krogerus 	val[0] = xe_mmio_read32(mmio, REG_SG_REMAP_ADDR_PREFIX);
60f0e53aadSHeikki Krogerus 	val[1] = xe_mmio_read32(mmio, REG_SG_REMAP_ADDR_POSTFIX);
61f0e53aadSHeikki Krogerus }
62f0e53aadSHeikki Krogerus 
63f0e53aadSHeikki Krogerus static void xe_i2c_client_work(struct work_struct *work)
64f0e53aadSHeikki Krogerus {
65f0e53aadSHeikki Krogerus 	struct xe_i2c *i2c = container_of(work, struct xe_i2c, work);
66f0e53aadSHeikki Krogerus 	struct i2c_board_info info = {
67f0e53aadSHeikki Krogerus 		.type	= "amc",
68f0e53aadSHeikki Krogerus 		.flags	= I2C_CLIENT_HOST_NOTIFY,
69f0e53aadSHeikki Krogerus 		.addr	= i2c->ep.addr[1],
70f0e53aadSHeikki Krogerus 	};
71f0e53aadSHeikki Krogerus 
72f0e53aadSHeikki Krogerus 	i2c->client[0] = i2c_new_client_device(i2c->adapter, &info);
73f0e53aadSHeikki Krogerus }
74f0e53aadSHeikki Krogerus 
75f0e53aadSHeikki Krogerus static int xe_i2c_notifier(struct notifier_block *nb, unsigned long action, void *data)
76f0e53aadSHeikki Krogerus {
77f0e53aadSHeikki Krogerus 	struct xe_i2c *i2c = container_of(nb, struct xe_i2c, bus_notifier);
78f0e53aadSHeikki Krogerus 	struct i2c_adapter *adapter = i2c_verify_adapter(data);
79f0e53aadSHeikki Krogerus 	struct device *dev = data;
80f0e53aadSHeikki Krogerus 
81f0e53aadSHeikki Krogerus 	if (action == BUS_NOTIFY_ADD_DEVICE &&
82f0e53aadSHeikki Krogerus 	    adapter && dev->parent == &i2c->pdev->dev) {
83f0e53aadSHeikki Krogerus 		i2c->adapter = adapter;
84f0e53aadSHeikki Krogerus 		schedule_work(&i2c->work);
85f0e53aadSHeikki Krogerus 		return NOTIFY_OK;
86f0e53aadSHeikki Krogerus 	}
87f0e53aadSHeikki Krogerus 
88f0e53aadSHeikki Krogerus 	return NOTIFY_DONE;
89f0e53aadSHeikki Krogerus }
90f0e53aadSHeikki Krogerus 
91f0e53aadSHeikki Krogerus static int xe_i2c_register_adapter(struct xe_i2c *i2c)
92f0e53aadSHeikki Krogerus {
93f0e53aadSHeikki Krogerus 	struct pci_dev *pci = to_pci_dev(i2c->drm_dev);
94f0e53aadSHeikki Krogerus 	struct platform_device *pdev;
95f0e53aadSHeikki Krogerus 	struct fwnode_handle *fwnode;
96f0e53aadSHeikki Krogerus 	int ret;
97f0e53aadSHeikki Krogerus 
98f0e53aadSHeikki Krogerus 	fwnode = fwnode_create_software_node(xe_i2c_adapter_properties, NULL);
99f0e53aadSHeikki Krogerus 	if (!fwnode)
100f0e53aadSHeikki Krogerus 		return -ENOMEM;
101f0e53aadSHeikki Krogerus 
102f0e53aadSHeikki Krogerus 	/*
103f0e53aadSHeikki Krogerus 	 * Not using platform_device_register_full() here because we don't have
104f0e53aadSHeikki Krogerus 	 * a handle to the platform_device before it returns. xe_i2c_notifier()
105f0e53aadSHeikki Krogerus 	 * uses that handle, but it may be called before
106f0e53aadSHeikki Krogerus 	 * platform_device_register_full() is done.
107f0e53aadSHeikki Krogerus 	 */
108f0e53aadSHeikki Krogerus 	pdev = platform_device_alloc(adapter_name, pci_dev_id(pci));
109f0e53aadSHeikki Krogerus 	if (!pdev) {
110f0e53aadSHeikki Krogerus 		ret = -ENOMEM;
111f0e53aadSHeikki Krogerus 		goto err_fwnode_remove;
112f0e53aadSHeikki Krogerus 	}
113f0e53aadSHeikki Krogerus 
114f0e53aadSHeikki Krogerus 	if (i2c->adapter_irq) {
115f0e53aadSHeikki Krogerus 		struct resource res;
116f0e53aadSHeikki Krogerus 
117f0e53aadSHeikki Krogerus 		res = DEFINE_RES_IRQ_NAMED(i2c->adapter_irq, "xe_i2c");
118f0e53aadSHeikki Krogerus 
119f0e53aadSHeikki Krogerus 		ret = platform_device_add_resources(pdev, &res, 1);
120f0e53aadSHeikki Krogerus 		if (ret)
121f0e53aadSHeikki Krogerus 			goto err_pdev_put;
122f0e53aadSHeikki Krogerus 	}
123f0e53aadSHeikki Krogerus 
124f0e53aadSHeikki Krogerus 	pdev->dev.parent = i2c->drm_dev;
125f0e53aadSHeikki Krogerus 	pdev->dev.fwnode = fwnode;
126f0e53aadSHeikki Krogerus 	i2c->adapter_node = fwnode;
127f0e53aadSHeikki Krogerus 	i2c->pdev = pdev;
128f0e53aadSHeikki Krogerus 
129f0e53aadSHeikki Krogerus 	ret = platform_device_add(pdev);
130f0e53aadSHeikki Krogerus 	if (ret)
131f0e53aadSHeikki Krogerus 		goto err_pdev_put;
132f0e53aadSHeikki Krogerus 
133f0e53aadSHeikki Krogerus 	return 0;
134f0e53aadSHeikki Krogerus 
135f0e53aadSHeikki Krogerus err_pdev_put:
136f0e53aadSHeikki Krogerus 	platform_device_put(pdev);
137f0e53aadSHeikki Krogerus err_fwnode_remove:
138f0e53aadSHeikki Krogerus 	fwnode_remove_software_node(fwnode);
139f0e53aadSHeikki Krogerus 
140f0e53aadSHeikki Krogerus 	return ret;
141f0e53aadSHeikki Krogerus }
142f0e53aadSHeikki Krogerus 
143f0e53aadSHeikki Krogerus static void xe_i2c_unregister_adapter(struct xe_i2c *i2c)
144f0e53aadSHeikki Krogerus {
145f0e53aadSHeikki Krogerus 	platform_device_unregister(i2c->pdev);
146f0e53aadSHeikki Krogerus 	fwnode_remove_software_node(i2c->adapter_node);
147f0e53aadSHeikki Krogerus }
148f0e53aadSHeikki Krogerus 
149f0e53aadSHeikki Krogerus /**
150f0e53aadSHeikki Krogerus  * xe_i2c_irq_handler: Handler for I2C interrupts
151f0e53aadSHeikki Krogerus  * @xe: xe device instance
152f0e53aadSHeikki Krogerus  * @master_ctl: interrupt register
153f0e53aadSHeikki Krogerus  *
154f0e53aadSHeikki Krogerus  * Forward interrupts generated by the I2C host adapter to the I2C host adapter
155f0e53aadSHeikki Krogerus  * driver.
156f0e53aadSHeikki Krogerus  */
157f0e53aadSHeikki Krogerus void xe_i2c_irq_handler(struct xe_device *xe, u32 master_ctl)
158f0e53aadSHeikki Krogerus {
159f0e53aadSHeikki Krogerus 	if (!xe->i2c || !xe->i2c->adapter_irq)
160f0e53aadSHeikki Krogerus 		return;
161f0e53aadSHeikki Krogerus 
162f0e53aadSHeikki Krogerus 	if (master_ctl & I2C_IRQ)
163f0e53aadSHeikki Krogerus 		generic_handle_irq_safe(xe->i2c->adapter_irq);
164f0e53aadSHeikki Krogerus }
165f0e53aadSHeikki Krogerus 
166f0e53aadSHeikki Krogerus static int xe_i2c_irq_map(struct irq_domain *h, unsigned int virq,
167f0e53aadSHeikki Krogerus 			  irq_hw_number_t hw_irq_num)
168f0e53aadSHeikki Krogerus {
169f0e53aadSHeikki Krogerus 	irq_set_chip_and_handler(virq, &dummy_irq_chip, handle_simple_irq);
170f0e53aadSHeikki Krogerus 	return 0;
171f0e53aadSHeikki Krogerus }
172f0e53aadSHeikki Krogerus 
173f0e53aadSHeikki Krogerus static const struct irq_domain_ops xe_i2c_irq_ops = {
174f0e53aadSHeikki Krogerus 	.map = xe_i2c_irq_map,
175f0e53aadSHeikki Krogerus };
176f0e53aadSHeikki Krogerus 
177f0e53aadSHeikki Krogerus static int xe_i2c_create_irq(struct xe_i2c *i2c)
178f0e53aadSHeikki Krogerus {
179f0e53aadSHeikki Krogerus 	struct irq_domain *domain;
180f0e53aadSHeikki Krogerus 
181f0e53aadSHeikki Krogerus 	if (!(i2c->ep.capabilities & XE_I2C_EP_CAP_IRQ))
182f0e53aadSHeikki Krogerus 		return 0;
183f0e53aadSHeikki Krogerus 
184f0e53aadSHeikki Krogerus 	domain = irq_domain_create_linear(dev_fwnode(i2c->drm_dev), 1, &xe_i2c_irq_ops, NULL);
185f0e53aadSHeikki Krogerus 	if (!domain)
186f0e53aadSHeikki Krogerus 		return -ENOMEM;
187f0e53aadSHeikki Krogerus 
188f0e53aadSHeikki Krogerus 	i2c->adapter_irq = irq_create_mapping(domain, 0);
189f0e53aadSHeikki Krogerus 	i2c->irqdomain = domain;
190f0e53aadSHeikki Krogerus 
191f0e53aadSHeikki Krogerus 	return 0;
192f0e53aadSHeikki Krogerus }
193f0e53aadSHeikki Krogerus 
194f0e53aadSHeikki Krogerus static void xe_i2c_remove_irq(struct xe_i2c *i2c)
195f0e53aadSHeikki Krogerus {
196f0e53aadSHeikki Krogerus 	if (!i2c->irqdomain)
197f0e53aadSHeikki Krogerus 		return;
198f0e53aadSHeikki Krogerus 
199f0e53aadSHeikki Krogerus 	irq_dispose_mapping(i2c->adapter_irq);
200f0e53aadSHeikki Krogerus 	irq_domain_remove(i2c->irqdomain);
201f0e53aadSHeikki Krogerus }
202f0e53aadSHeikki Krogerus 
203f0e53aadSHeikki Krogerus static int xe_i2c_read(void *context, unsigned int reg, unsigned int *val)
204f0e53aadSHeikki Krogerus {
205f0e53aadSHeikki Krogerus 	struct xe_i2c *i2c = context;
206f0e53aadSHeikki Krogerus 
207f0e53aadSHeikki Krogerus 	*val = xe_mmio_read32(i2c->mmio, XE_REG(reg + I2C_MEM_SPACE_OFFSET));
208f0e53aadSHeikki Krogerus 
209f0e53aadSHeikki Krogerus 	return 0;
210f0e53aadSHeikki Krogerus }
211f0e53aadSHeikki Krogerus 
212f0e53aadSHeikki Krogerus static int xe_i2c_write(void *context, unsigned int reg, unsigned int val)
213f0e53aadSHeikki Krogerus {
214f0e53aadSHeikki Krogerus 	struct xe_i2c *i2c = context;
215f0e53aadSHeikki Krogerus 
216f0e53aadSHeikki Krogerus 	xe_mmio_write32(i2c->mmio, XE_REG(reg + I2C_MEM_SPACE_OFFSET), val);
217f0e53aadSHeikki Krogerus 
218f0e53aadSHeikki Krogerus 	return 0;
219f0e53aadSHeikki Krogerus }
220f0e53aadSHeikki Krogerus 
221f0e53aadSHeikki Krogerus static const struct regmap_config i2c_regmap_config = {
222f0e53aadSHeikki Krogerus 	.reg_bits = 32,
223f0e53aadSHeikki Krogerus 	.val_bits = 32,
224f0e53aadSHeikki Krogerus 	.reg_read = xe_i2c_read,
225f0e53aadSHeikki Krogerus 	.reg_write = xe_i2c_write,
226f0e53aadSHeikki Krogerus 	.fast_io = true,
227f0e53aadSHeikki Krogerus };
228f0e53aadSHeikki Krogerus 
229*0ea07b69SRaag Jadav void xe_i2c_pm_suspend(struct xe_device *xe)
230*0ea07b69SRaag Jadav {
231*0ea07b69SRaag Jadav 	struct xe_mmio *mmio = xe_root_tile_mmio(xe);
232*0ea07b69SRaag Jadav 
233*0ea07b69SRaag Jadav 	if (!xe->i2c || xe->i2c->ep.cookie != XE_I2C_EP_COOKIE_DEVICE)
234*0ea07b69SRaag Jadav 		return;
235*0ea07b69SRaag Jadav 
236*0ea07b69SRaag Jadav 	xe_mmio_rmw32(mmio, I2C_CONFIG_PMCSR, PCI_PM_CTRL_STATE_MASK, (__force u32)PCI_D3hot);
237*0ea07b69SRaag Jadav 	drm_dbg(&xe->drm, "pmcsr: 0x%08x\n", xe_mmio_read32(mmio, I2C_CONFIG_PMCSR));
238*0ea07b69SRaag Jadav }
239*0ea07b69SRaag Jadav 
240*0ea07b69SRaag Jadav void xe_i2c_pm_resume(struct xe_device *xe, bool d3cold)
241*0ea07b69SRaag Jadav {
242*0ea07b69SRaag Jadav 	struct xe_mmio *mmio = xe_root_tile_mmio(xe);
243*0ea07b69SRaag Jadav 
244*0ea07b69SRaag Jadav 	if (!xe->i2c || xe->i2c->ep.cookie != XE_I2C_EP_COOKIE_DEVICE)
245*0ea07b69SRaag Jadav 		return;
246*0ea07b69SRaag Jadav 
247*0ea07b69SRaag Jadav 	if (d3cold)
248*0ea07b69SRaag Jadav 		xe_mmio_rmw32(mmio, I2C_CONFIG_CMD, 0, PCI_COMMAND_MEMORY);
249*0ea07b69SRaag Jadav 
250*0ea07b69SRaag Jadav 	xe_mmio_rmw32(mmio, I2C_CONFIG_PMCSR, PCI_PM_CTRL_STATE_MASK, (__force u32)PCI_D0);
251*0ea07b69SRaag Jadav 	drm_dbg(&xe->drm, "pmcsr: 0x%08x\n", xe_mmio_read32(mmio, I2C_CONFIG_PMCSR));
252*0ea07b69SRaag Jadav }
253*0ea07b69SRaag Jadav 
254f0e53aadSHeikki Krogerus static void xe_i2c_remove(void *data)
255f0e53aadSHeikki Krogerus {
256f0e53aadSHeikki Krogerus 	struct xe_i2c *i2c = data;
257f0e53aadSHeikki Krogerus 	unsigned int i;
258f0e53aadSHeikki Krogerus 
259f0e53aadSHeikki Krogerus 	for (i = 0; i < XE_I2C_MAX_CLIENTS; i++)
260f0e53aadSHeikki Krogerus 		i2c_unregister_device(i2c->client[i]);
261f0e53aadSHeikki Krogerus 
262f0e53aadSHeikki Krogerus 	bus_unregister_notifier(&i2c_bus_type, &i2c->bus_notifier);
263f0e53aadSHeikki Krogerus 	xe_i2c_unregister_adapter(i2c);
264f0e53aadSHeikki Krogerus 	xe_i2c_remove_irq(i2c);
265f0e53aadSHeikki Krogerus }
266f0e53aadSHeikki Krogerus 
267f0e53aadSHeikki Krogerus /**
268f0e53aadSHeikki Krogerus  * xe_i2c_probe: Probe the I2C host adapter and the I2C clients attached to it
269f0e53aadSHeikki Krogerus  * @xe: xe device instance
270f0e53aadSHeikki Krogerus  *
271f0e53aadSHeikki Krogerus  * Register all the I2C devices described in the I2C Endpoint data structure.
272f0e53aadSHeikki Krogerus  *
273f0e53aadSHeikki Krogerus  * Return: 0 on success, error code on failure
274f0e53aadSHeikki Krogerus  */
275f0e53aadSHeikki Krogerus int xe_i2c_probe(struct xe_device *xe)
276f0e53aadSHeikki Krogerus {
277f0e53aadSHeikki Krogerus 	struct device *drm_dev = xe->drm.dev;
278f0e53aadSHeikki Krogerus 	struct xe_i2c_endpoint ep;
279f0e53aadSHeikki Krogerus 	struct regmap *regmap;
280f0e53aadSHeikki Krogerus 	struct xe_i2c *i2c;
281f0e53aadSHeikki Krogerus 	int ret;
282f0e53aadSHeikki Krogerus 
283f0e53aadSHeikki Krogerus 	if (xe->info.platform != XE_BATTLEMAGE)
284f0e53aadSHeikki Krogerus 		return 0;
285f0e53aadSHeikki Krogerus 
286f0e53aadSHeikki Krogerus 	xe_i2c_read_endpoint(xe_root_tile_mmio(xe), &ep);
287f0e53aadSHeikki Krogerus 	if (ep.cookie != XE_I2C_EP_COOKIE_DEVICE)
288f0e53aadSHeikki Krogerus 		return 0;
289f0e53aadSHeikki Krogerus 
290f0e53aadSHeikki Krogerus 	i2c = devm_kzalloc(drm_dev, sizeof(*i2c), GFP_KERNEL);
291f0e53aadSHeikki Krogerus 	if (!i2c)
292f0e53aadSHeikki Krogerus 		return -ENOMEM;
293f0e53aadSHeikki Krogerus 
294f0e53aadSHeikki Krogerus 	INIT_WORK(&i2c->work, xe_i2c_client_work);
295f0e53aadSHeikki Krogerus 	i2c->mmio = xe_root_tile_mmio(xe);
296f0e53aadSHeikki Krogerus 	i2c->drm_dev = drm_dev;
297f0e53aadSHeikki Krogerus 	i2c->ep = ep;
298*0ea07b69SRaag Jadav 	xe->i2c = i2c;
299*0ea07b69SRaag Jadav 
300*0ea07b69SRaag Jadav 	/* PCI PM isn't aware of this device, bring it up and match it with SGUnit state. */
301*0ea07b69SRaag Jadav 	xe_i2c_pm_resume(xe, true);
302f0e53aadSHeikki Krogerus 
303f0e53aadSHeikki Krogerus 	regmap = devm_regmap_init(drm_dev, NULL, i2c, &i2c_regmap_config);
304f0e53aadSHeikki Krogerus 	if (IS_ERR(regmap))
305f0e53aadSHeikki Krogerus 		return PTR_ERR(regmap);
306f0e53aadSHeikki Krogerus 
307f0e53aadSHeikki Krogerus 	i2c->bus_notifier.notifier_call = xe_i2c_notifier;
308f0e53aadSHeikki Krogerus 	ret = bus_register_notifier(&i2c_bus_type, &i2c->bus_notifier);
309f0e53aadSHeikki Krogerus 	if (ret)
310f0e53aadSHeikki Krogerus 		return ret;
311f0e53aadSHeikki Krogerus 
312f0e53aadSHeikki Krogerus 	ret = xe_i2c_create_irq(i2c);
313f0e53aadSHeikki Krogerus 	if (ret)
314f0e53aadSHeikki Krogerus 		goto err_unregister_notifier;
315f0e53aadSHeikki Krogerus 
316f0e53aadSHeikki Krogerus 	ret = xe_i2c_register_adapter(i2c);
317f0e53aadSHeikki Krogerus 	if (ret)
318f0e53aadSHeikki Krogerus 		goto err_remove_irq;
319f0e53aadSHeikki Krogerus 
320f0e53aadSHeikki Krogerus 	return devm_add_action_or_reset(drm_dev, xe_i2c_remove, i2c);
321f0e53aadSHeikki Krogerus 
322f0e53aadSHeikki Krogerus err_remove_irq:
323f0e53aadSHeikki Krogerus 	xe_i2c_remove_irq(i2c);
324f0e53aadSHeikki Krogerus 
325f0e53aadSHeikki Krogerus err_unregister_notifier:
326f0e53aadSHeikki Krogerus 	bus_unregister_notifier(&i2c_bus_type, &i2c->bus_notifier);
327f0e53aadSHeikki Krogerus 
328f0e53aadSHeikki Krogerus 	return ret;
329f0e53aadSHeikki Krogerus }
330