^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * GPIO-controlled multiplexer driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2017 Axentia Technologies AB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Peter Rosin <peda@axentia.se>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mux/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct mux_gpio {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct gpio_descs *gpios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static int mux_gpio_set(struct mux_control *mux, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct mux_gpio *mux_gpio = mux_chip_priv(mux->chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) DECLARE_BITMAP(values, BITS_PER_TYPE(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) values[0] = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) gpiod_set_array_value_cansleep(mux_gpio->gpios->ndescs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) mux_gpio->gpios->desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) mux_gpio->gpios->info, values);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static const struct mux_control_ops mux_gpio_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .set = mux_gpio_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static const struct of_device_id mux_gpio_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) { .compatible = "gpio-mux", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) MODULE_DEVICE_TABLE(of, mux_gpio_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static int mux_gpio_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct mux_chip *mux_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct mux_gpio *mux_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int pins;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) s32 idle_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) pins = gpiod_count(dev, "mux");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (pins < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return pins;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (IS_ERR(mux_chip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return PTR_ERR(mux_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) mux_gpio = mux_chip_priv(mux_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) mux_chip->ops = &mux_gpio_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) mux_gpio->gpios = devm_gpiod_get_array(dev, "mux", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (IS_ERR(mux_gpio->gpios)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ret = PTR_ERR(mux_gpio->gpios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) dev_err(dev, "failed to get gpios\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) WARN_ON(pins != mux_gpio->gpios->ndescs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) mux_chip->mux->states = 1 << pins;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ret = device_property_read_u32(dev, "idle-state", (u32 *)&idle_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (ret >= 0 && idle_state != MUX_IDLE_AS_IS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (idle_state < 0 || idle_state >= mux_chip->mux->states) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) dev_err(dev, "invalid idle-state %u\n", idle_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) mux_chip->mux->idle_state = idle_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ret = devm_mux_chip_register(dev, mux_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) dev_info(dev, "%u-way mux-controller registered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) mux_chip->mux->states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static struct platform_driver mux_gpio_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .name = "gpio-mux",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .of_match_table = of_match_ptr(mux_gpio_dt_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .probe = mux_gpio_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) module_platform_driver(mux_gpio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) MODULE_DESCRIPTION("GPIO-controlled multiplexer driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) MODULE_LICENSE("GPL v2");