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(dev), "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