xref: /openbmc/u-boot/drivers/i2c/muxes/pca954x.c (revision ad5b5801)
1 /*
2  * Copyright (C) 2015 - 2016 Xilinx, Inc.
3  * Written by Michal Simek
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <i2c.h>
12 #include <asm/gpio.h>
13 
14 DECLARE_GLOBAL_DATA_PTR;
15 
16 struct pca954x_priv {
17 	u32 addr; /* I2C mux address */
18 	u32 width; /* I2C mux width - number of busses */
19 };
20 
21 static int pca954x_deselect(struct udevice *mux, struct udevice *bus,
22 			    uint channel)
23 {
24 	struct pca954x_priv *priv = dev_get_priv(mux);
25 	uchar byte = 0;
26 
27 	return dm_i2c_write(mux, priv->addr, &byte, 1);
28 }
29 
30 static int pca954x_select(struct udevice *mux, struct udevice *bus,
31 			  uint channel)
32 {
33 	struct pca954x_priv *priv = dev_get_priv(mux);
34 	uchar byte = 1 << channel;
35 
36 	return dm_i2c_write(mux, priv->addr, &byte, 1);
37 }
38 
39 static const struct i2c_mux_ops pca954x_ops = {
40 	.select = pca954x_select,
41 	.deselect = pca954x_deselect,
42 };
43 
44 static const struct udevice_id pca954x_ids[] = {
45 	{ .compatible = "nxp,pca9548", .data = (ulong)8 },
46 	{ .compatible = "nxp,pca9544", .data = (ulong)4 },
47 	{ }
48 };
49 
50 static int pca954x_ofdata_to_platdata(struct udevice *dev)
51 {
52 	struct pca954x_priv *priv = dev_get_priv(dev);
53 
54 	priv->addr = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", 0);
55 	if (!priv->addr) {
56 		debug("MUX not found\n");
57 		return -ENODEV;
58 	}
59 	priv->width = dev_get_driver_data(dev);
60 
61 	if (!priv->width) {
62 		debug("No I2C MUX width specified\n");
63 		return -EINVAL;
64 	}
65 
66 	debug("Device %s at 0x%x with width %d\n",
67 	      dev->name, priv->addr, priv->width);
68 
69 	return 0;
70 }
71 
72 U_BOOT_DRIVER(pca954x) = {
73 	.name = "pca954x",
74 	.id = UCLASS_I2C_MUX,
75 	.of_match = pca954x_ids,
76 	.ops = &pca954x_ops,
77 	.ofdata_to_platdata = pca954x_ofdata_to_platdata,
78 	.priv_auto_alloc_size = sizeof(struct pca954x_priv),
79 };
80