|
@@ -21,6 +21,7 @@ struct gpiomux {
|
|
|
struct i2c_adapter *parent;
|
|
|
struct i2c_adapter **adap; /* child busses */
|
|
|
struct i2c_mux_gpio_platform_data data;
|
|
|
+ unsigned gpio_base;
|
|
|
};
|
|
|
|
|
|
static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
|
|
@@ -28,7 +29,8 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
|
|
|
int i;
|
|
|
|
|
|
for (i = 0; i < mux->data.n_gpios; i++)
|
|
|
- gpio_set_value(mux->data.gpios[i], val & (1 << i));
|
|
|
+ gpio_set_value(mux->gpio_base + mux->data.gpios[i],
|
|
|
+ val & (1 << i));
|
|
|
}
|
|
|
|
|
|
static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan)
|
|
@@ -49,13 +51,19 @@ static int i2c_mux_gpio_deselect(struct i2c_adapter *adap, void *data, u32 chan)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int __devinit match_gpio_chip_by_label(struct gpio_chip *chip,
|
|
|
+ void *data)
|
|
|
+{
|
|
|
+ return !strcmp(chip->label, data);
|
|
|
+}
|
|
|
+
|
|
|
static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
struct gpiomux *mux;
|
|
|
struct i2c_mux_gpio_platform_data *pdata;
|
|
|
struct i2c_adapter *parent;
|
|
|
int (*deselect) (struct i2c_adapter *, void *, u32);
|
|
|
- unsigned initial_state;
|
|
|
+ unsigned initial_state, gpio_base;
|
|
|
int i, ret;
|
|
|
|
|
|
pdata = pdev->dev.platform_data;
|
|
@@ -64,6 +72,23 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
|
|
|
return -ENODEV;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * If a GPIO chip name is provided, the GPIO pin numbers provided are
|
|
|
+ * relative to its base GPIO number. Otherwise they are absolute.
|
|
|
+ */
|
|
|
+ if (pdata->gpio_chip) {
|
|
|
+ struct gpio_chip *gpio;
|
|
|
+
|
|
|
+ gpio = gpiochip_find(pdata->gpio_chip,
|
|
|
+ match_gpio_chip_by_label);
|
|
|
+ if (!gpio)
|
|
|
+ return -EPROBE_DEFER;
|
|
|
+
|
|
|
+ gpio_base = gpio->base;
|
|
|
+ } else {
|
|
|
+ gpio_base = 0;
|
|
|
+ }
|
|
|
+
|
|
|
parent = i2c_get_adapter(pdata->parent);
|
|
|
if (!parent) {
|
|
|
dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
|
|
@@ -79,6 +104,7 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
|
|
|
|
|
|
mux->parent = parent;
|
|
|
mux->data = *pdata;
|
|
|
+ mux->gpio_base = gpio_base;
|
|
|
mux->adap = devm_kzalloc(&pdev->dev,
|
|
|
sizeof(*mux->adap) * pdata->n_values,
|
|
|
GFP_KERNEL);
|
|
@@ -96,10 +122,10 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < pdata->n_gpios; i++) {
|
|
|
- ret = gpio_request(pdata->gpios[i], "i2c-mux-gpio");
|
|
|
+ ret = gpio_request(gpio_base + pdata->gpios[i], "i2c-mux-gpio");
|
|
|
if (ret)
|
|
|
goto err_request_gpio;
|
|
|
- gpio_direction_output(pdata->gpios[i],
|
|
|
+ gpio_direction_output(gpio_base + pdata->gpios[i],
|
|
|
initial_state & (1 << i));
|
|
|
}
|
|
|
|
|
@@ -130,7 +156,7 @@ add_adapter_failed:
|
|
|
i = pdata->n_gpios;
|
|
|
err_request_gpio:
|
|
|
for (; i > 0; i--)
|
|
|
- gpio_free(pdata->gpios[i - 1]);
|
|
|
+ gpio_free(gpio_base + pdata->gpios[i - 1]);
|
|
|
alloc_failed:
|
|
|
i2c_put_adapter(parent);
|
|
|
|
|
@@ -146,7 +172,7 @@ static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev)
|
|
|
i2c_del_mux_adapter(mux->adap[i]);
|
|
|
|
|
|
for (i = 0; i < mux->data.n_gpios; i++)
|
|
|
- gpio_free(mux->data.gpios[i]);
|
|
|
+ gpio_free(mux->gpio_base + mux->data.gpios[i]);
|
|
|
|
|
|
platform_set_drvdata(pdev, NULL);
|
|
|
i2c_put_adapter(mux->parent);
|