1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2015 - 2016 Xilinx, Inc. 4 * Copyright (C) 2017 National Instruments Corp 5 * Written by Michal Simek 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <i2c.h> 12 13 #include <asm-generic/gpio.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 enum pca_type { 18 PCA9544, 19 PCA9547, 20 PCA9548 21 }; 22 23 struct chip_desc { 24 u8 enable; 25 enum muxtype { 26 pca954x_ismux = 0, 27 pca954x_isswi, 28 } muxtype; 29 u32 width; 30 }; 31 32 struct pca954x_priv { 33 u32 addr; /* I2C mux address */ 34 u32 width; /* I2C mux width - number of busses */ 35 struct gpio_desc gpio_mux_reset; 36 }; 37 38 static const struct chip_desc chips[] = { 39 [PCA9544] = { 40 .enable = 0x4, 41 .muxtype = pca954x_ismux, 42 .width = 4, 43 }, 44 [PCA9547] = { 45 .enable = 0x8, 46 .muxtype = pca954x_ismux, 47 .width = 8, 48 }, 49 [PCA9548] = { 50 .enable = 0x8, 51 .muxtype = pca954x_isswi, 52 .width = 8, 53 }, 54 }; 55 56 static int pca954x_deselect(struct udevice *mux, struct udevice *bus, 57 uint channel) 58 { 59 struct pca954x_priv *priv = dev_get_priv(mux); 60 uchar byte = 0; 61 62 return dm_i2c_write(mux, priv->addr, &byte, 1); 63 } 64 65 static int pca954x_select(struct udevice *mux, struct udevice *bus, 66 uint channel) 67 { 68 struct pca954x_priv *priv = dev_get_priv(mux); 69 const struct chip_desc *chip = &chips[dev_get_driver_data(mux)]; 70 uchar byte; 71 72 if (chip->muxtype == pca954x_ismux) 73 byte = channel | chip->enable; 74 else 75 byte = 1 << channel; 76 77 return dm_i2c_write(mux, priv->addr, &byte, 1); 78 } 79 80 static const struct i2c_mux_ops pca954x_ops = { 81 .select = pca954x_select, 82 .deselect = pca954x_deselect, 83 }; 84 85 static const struct udevice_id pca954x_ids[] = { 86 { .compatible = "nxp,pca9544", .data = PCA9544 }, 87 { .compatible = "nxp,pca9547", .data = PCA9547 }, 88 { .compatible = "nxp,pca9548", .data = PCA9548 }, 89 { } 90 }; 91 92 static int pca954x_ofdata_to_platdata(struct udevice *dev) 93 { 94 struct pca954x_priv *priv = dev_get_priv(dev); 95 const struct chip_desc *chip = &chips[dev_get_driver_data(dev)]; 96 97 priv->addr = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "reg", 0); 98 if (!priv->addr) { 99 debug("MUX not found\n"); 100 return -ENODEV; 101 } 102 priv->width = chip->width; 103 104 if (!priv->width) { 105 debug("No I2C MUX width specified\n"); 106 return -EINVAL; 107 } 108 109 debug("Device %s at 0x%x with width %d\n", 110 dev->name, priv->addr, priv->width); 111 112 return 0; 113 } 114 115 static int pca954x_probe(struct udevice *dev) 116 { 117 if (IS_ENABLED(CONFIG_DM_GPIO)) { 118 struct pca954x_priv *priv = dev_get_priv(dev); 119 int err; 120 121 err = gpio_request_by_name(dev, "reset-gpios", 0, 122 &priv->gpio_mux_reset, GPIOD_IS_OUT); 123 124 /* it's optional so only bail if we get a real error */ 125 if (err && (err != -ENOENT)) 126 return err; 127 128 /* dm will take care of polarity */ 129 if (dm_gpio_is_valid(&priv->gpio_mux_reset)) 130 dm_gpio_set_value(&priv->gpio_mux_reset, 0); 131 } 132 133 return 0; 134 } 135 136 static int pca954x_remove(struct udevice *dev) 137 { 138 if (IS_ENABLED(CONFIG_DM_GPIO)) { 139 struct pca954x_priv *priv = dev_get_priv(dev); 140 141 if (dm_gpio_is_valid(&priv->gpio_mux_reset)) 142 dm_gpio_free(dev, &priv->gpio_mux_reset); 143 } 144 145 return 0; 146 } 147 148 U_BOOT_DRIVER(pca954x) = { 149 .name = "pca954x", 150 .id = UCLASS_I2C_MUX, 151 .of_match = pca954x_ids, 152 .probe = pca954x_probe, 153 .remove = pca954x_remove, 154 .ops = &pca954x_ops, 155 .ofdata_to_platdata = pca954x_ofdata_to_platdata, 156 .priv_auto_alloc_size = sizeof(struct pca954x_priv), 157 }; 158