static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id) { struct iio_dev *indio_dev = i2c_mux_priv(muxc); struct inv_mpu6050_state *st = iio_priv(indio_dev); int ret = 0; /* Use the same mutex which was used everywhere to protect power-op */ mutex_lock(&indio_dev->mlock); if (!st->powerup_count) { ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0); if (ret) goto write_error; usleep_range(INV_MPU6050_REG_UP_TIME_MIN, INV_MPU6050_REG_UP_TIME_MAX); } if (!ret) { st->powerup_count++; ret = regmap_write(st->map, st->reg->int_pin_cfg, INV_MPU6050_INT_PIN_CFG | INV_MPU6050_BIT_BYPASS_EN); } write_error: mutex_unlock(&indio_dev->mlock); return ret; }
static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan) { struct gpiomux *mux = i2c_mux_priv(muxc); i2c_mux_gpio_set(mux, mux->data.idle); return 0; }
static int mpu3050_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id) { struct mpu3050 *mpu3050 = i2c_mux_priv(mux); pm_runtime_mark_last_busy(mpu3050->dev); pm_runtime_put_autosuspend(mpu3050->dev); return 0; }
static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan) { struct gpiomux *mux = i2c_mux_priv(muxc); i2c_mux_gpio_set(mux, chan); return 0; }
static int mpu3050_i2c_bypass_select(struct i2c_mux_core *mux, u32 chan_id) { struct mpu3050 *mpu3050 = i2c_mux_priv(mux); /* Just power up the device, that is all that is needed */ pm_runtime_get_sync(mpu3050->dev); return 0; }
static int i2c_mux_reg_deselect(struct i2c_mux_core *muxc, u32 chan) { struct regmux *mux = i2c_mux_priv(muxc); if (mux->data.idle_in_use) return i2c_mux_reg_set(mux, mux->data.idle); return 0; }
/** * i2c_arbitrator_deselect - release the I2C bus * * Release the I2C bus using the GPIO-based signalling protocol. */ static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan) { const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc); /* Release the bus and wait for the other master to notice */ gpio_set_value(arb->our_gpio, arb->our_gpio_release); udelay(arb->slew_delay_us); return 0; }
static int mlxcpld_mux_deselect(struct i2c_mux_core *muxc, u32 chan) { struct mlxcpld_mux *data = i2c_mux_priv(muxc); struct i2c_client *client = data->client; /* Deselect active channel */ data->last_chan = 0; return mlxcpld_mux_reg_write(muxc->parent, client, data->last_chan); }
static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan) { struct mlxcpld_mux *data = i2c_mux_priv(muxc); struct i2c_client *client = data->client; u8 regval = chan + 1; int err = 0; /* Only select the channel if its different from the last channel */ if (data->last_chan != regval) { err = mlxcpld_mux_reg_write(muxc->parent, client, regval); data->last_chan = err < 0 ? 0 : regval; } return err; }
static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id) { struct iio_dev *indio_dev = i2c_mux_priv(muxc); struct inv_mpu6050_state *st = iio_priv(indio_dev); mutex_lock(&indio_dev->mlock); /* It doesn't really mattter, if any of the calls fails */ regmap_write(st->map, st->reg->int_pin_cfg, INV_MPU6050_INT_PIN_CFG); st->powerup_count--; if (!st->powerup_count) regmap_write(st->map, st->reg->pwr_mgmt_1, INV_MPU6050_BIT_SLEEP); mutex_unlock(&indio_dev->mlock); return 0; }
/* Probe/reomove functions */ static int mlxcpld_mux_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev); struct i2c_mux_core *muxc; int num, force; struct mlxcpld_mux *data; int err; if (!pdata) return -EINVAL; if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return -ENODEV; muxc = i2c_mux_alloc(adap, &client->dev, CPLD_MUX_MAX_NCHANS, sizeof(*data), 0, mlxcpld_mux_select_chan, mlxcpld_mux_deselect); if (!muxc) return -ENOMEM; data = i2c_mux_priv(muxc); i2c_set_clientdata(client, muxc); data->client = client; data->last_chan = 0; /* force the first selection */ /* Create an adapter for each channel. */ for (num = 0; num < CPLD_MUX_MAX_NCHANS; num++) { if (num >= pdata->num_adaps) /* discard unconfigured channels */ break; force = pdata->adap_ids[num]; err = i2c_mux_add_adapter(muxc, force, num, 0); if (err) goto virt_reg_failed; } return 0; virt_reg_failed: i2c_mux_del_adapters(muxc); return err; }
/** * i2c_arbitrator_select - claim the I2C bus * * Use the GPIO-based signalling protocol; return -EBUSY if we fail. */ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan) { const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc); unsigned long stop_retry, stop_time; /* Start a round of trying to claim the bus */ stop_time = jiffies + usecs_to_jiffies(arb->wait_free_us) + 1; do { /* Indicate that we want to claim the bus */ gpio_set_value(arb->our_gpio, !arb->our_gpio_release); udelay(arb->slew_delay_us); /* Wait for the other master to release it */ stop_retry = jiffies + usecs_to_jiffies(arb->wait_retry_us) + 1; while (time_before(jiffies, stop_retry)) { int gpio_val = !!gpio_get_value(arb->their_gpio); if (gpio_val == arb->their_gpio_release) { /* We got it, so return */ return 0; } usleep_range(50, 200); } /* It didn't release, so give up, wait, and try again */ gpio_set_value(arb->our_gpio, arb->our_gpio_release); usleep_range(arb->wait_retry_us, arb->wait_retry_us * 2); } while (time_before(jiffies, stop_time)); /* Give up, release our claim */ gpio_set_value(arb->our_gpio, arb->our_gpio_release); udelay(arb->slew_delay_us); dev_err(muxc->dev, "Could not claim bus, timeout\n"); return -EBUSY; }
static int i2c_mux_reg_select(struct i2c_mux_core *muxc, u32 chan) { struct regmux *mux = i2c_mux_priv(muxc); return i2c_mux_reg_set(mux, chan); }
static int i2c_arbitrator_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct device_node *parent_np; struct i2c_mux_core *muxc; struct i2c_arbitrator_data *arb; enum of_gpio_flags gpio_flags; unsigned long out_init; int ret; /* We only support probing from device tree; no platform_data */ if (!np) { dev_err(dev, "Cannot find device tree node\n"); return -ENODEV; } if (dev_get_platdata(dev)) { dev_err(dev, "Platform data is not supported\n"); return -EINVAL; } muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), I2C_MUX_ARBITRATOR, i2c_arbitrator_select, i2c_arbitrator_deselect); if (!muxc) return -ENOMEM; arb = i2c_mux_priv(muxc); platform_set_drvdata(pdev, muxc); /* Request GPIOs */ ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags); if (!gpio_is_valid(ret)) { if (ret != -EPROBE_DEFER) dev_err(dev, "Error getting our-claim-gpio\n"); return ret; } arb->our_gpio = ret; arb->our_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW); out_init = (gpio_flags & OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ret = devm_gpio_request_one(dev, arb->our_gpio, out_init, "our-claim-gpio"); if (ret) { if (ret != -EPROBE_DEFER) dev_err(dev, "Error requesting our-claim-gpio\n"); return ret; } ret = of_get_named_gpio_flags(np, "their-claim-gpios", 0, &gpio_flags); if (!gpio_is_valid(ret)) { if (ret != -EPROBE_DEFER) dev_err(dev, "Error getting their-claim-gpio\n"); return ret; } arb->their_gpio = ret; arb->their_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW); ret = devm_gpio_request_one(dev, arb->their_gpio, GPIOF_IN, "their-claim-gpio"); if (ret) { if (ret != -EPROBE_DEFER) dev_err(dev, "Error requesting their-claim-gpio\n"); return ret; } /* At the moment we only support a single two master (us + 1 other) */ if (gpio_is_valid(of_get_named_gpio(np, "their-claim-gpios", 1))) { dev_err(dev, "Only one other master is supported\n"); return -EINVAL; } /* Arbitration parameters */ if (of_property_read_u32(np, "slew-delay-us", &arb->slew_delay_us)) arb->slew_delay_us = 10; if (of_property_read_u32(np, "wait-retry-us", &arb->wait_retry_us)) arb->wait_retry_us = 3000; if (of_property_read_u32(np, "wait-free-us", &arb->wait_free_us)) arb->wait_free_us = 50000; /* Find our parent */ parent_np = of_parse_phandle(np, "i2c-parent", 0); if (!parent_np) { dev_err(dev, "Cannot parse i2c-parent\n"); return -EINVAL; } muxc->parent = of_get_i2c_adapter_by_node(parent_np); of_node_put(parent_np); if (!muxc->parent) { dev_err(dev, "Cannot find parent bus\n"); return -EPROBE_DEFER; } /* Actually add the mux adapter */ ret = i2c_mux_add_adapter(muxc, 0, 0, 0); if (ret) { dev_err(dev, "Failed to add adapter\n"); i2c_put_adapter(muxc->parent); } return ret; }