1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * GPIO line mux which acts as virtual gpiochip and provides a 1-to-many 4 * mapping between virtual GPIOs and a real GPIO + multiplexer. 5 * 6 * Copyright (c) 2025 Jonas Jelonek <jelonek.jonas@gmail.com> 7 */ 8 9 #include <linux/gpio/consumer.h> 10 #include <linux/gpio/driver.h> 11 #include <linux/mutex.h> 12 #include <linux/mux/consumer.h> 13 #include <linux/platform_device.h> 14 15 #define MUX_SELECT_DELAY_US 100 16 17 struct gpio_lmux { 18 struct gpio_chip gc; 19 struct mux_control *mux; 20 struct gpio_desc *muxed_gpio; 21 22 u32 num_gpio_mux_states; 23 unsigned int gpio_mux_states[] __counted_by(num_gpio_mux_states); 24 }; 25 26 static int gpio_lmux_gpio_get(struct gpio_chip *gc, unsigned int offset) 27 { 28 struct gpio_lmux *glm = gpiochip_get_data(gc); 29 int ret; 30 31 ret = mux_control_select_delay(glm->mux, glm->gpio_mux_states[offset], 32 MUX_SELECT_DELAY_US); 33 if (ret < 0) 34 return ret; 35 36 ret = gpiod_get_raw_value_cansleep(glm->muxed_gpio); 37 mux_control_deselect(glm->mux); 38 return ret; 39 } 40 41 static int gpio_lmux_gpio_get_direction(struct gpio_chip *gc, 42 unsigned int offset) 43 { 44 return GPIO_LINE_DIRECTION_IN; 45 } 46 47 static int gpio_lmux_probe(struct platform_device *pdev) 48 { 49 struct device *dev = &pdev->dev; 50 struct gpio_lmux *glm; 51 unsigned int ngpio; 52 size_t size; 53 int ret; 54 55 ngpio = device_property_count_u32(dev, "gpio-line-mux-states"); 56 if (!ngpio) 57 return -EINVAL; 58 59 size = struct_size(glm, gpio_mux_states, ngpio); 60 glm = devm_kzalloc(dev, size, GFP_KERNEL); 61 if (!glm) 62 return -ENOMEM; 63 64 glm->gc.base = -1; 65 glm->gc.can_sleep = true; 66 glm->gc.fwnode = dev_fwnode(dev); 67 glm->gc.label = dev_name(dev); 68 glm->gc.ngpio = ngpio; 69 glm->gc.owner = THIS_MODULE; 70 glm->gc.parent = dev; 71 72 glm->gc.get = gpio_lmux_gpio_get; 73 glm->gc.get_direction = gpio_lmux_gpio_get_direction; 74 75 glm->mux = devm_mux_control_get(dev, NULL); 76 if (IS_ERR(glm->mux)) 77 return dev_err_probe(dev, PTR_ERR(glm->mux), 78 "could not get mux controller\n"); 79 80 glm->muxed_gpio = devm_gpiod_get(dev, "muxed", GPIOD_IN); 81 if (IS_ERR(glm->muxed_gpio)) 82 return dev_err_probe(dev, PTR_ERR(glm->muxed_gpio), 83 "could not get muxed-gpio\n"); 84 85 glm->num_gpio_mux_states = ngpio; 86 ret = device_property_read_u32_array(dev, "gpio-line-mux-states", 87 &glm->gpio_mux_states[0], ngpio); 88 if (ret) 89 return dev_err_probe(dev, ret, "could not get mux states\n"); 90 91 ret = devm_gpiochip_add_data(dev, &glm->gc, glm); 92 if (ret) 93 return dev_err_probe(dev, ret, "failed to add gpiochip\n"); 94 95 return 0; 96 } 97 98 static const struct of_device_id gpio_lmux_of_match[] = { 99 { .compatible = "gpio-line-mux" }, 100 { } 101 }; 102 MODULE_DEVICE_TABLE(of, gpio_lmux_of_match); 103 104 static struct platform_driver gpio_lmux_driver = { 105 .driver = { 106 .name = "gpio-line-mux", 107 .of_match_table = gpio_lmux_of_match, 108 }, 109 .probe = gpio_lmux_probe, 110 }; 111 module_platform_driver(gpio_lmux_driver); 112 113 MODULE_AUTHOR("Jonas Jelonek <jelonek.jonas@gmail.com>"); 114 MODULE_DESCRIPTION("GPIO line mux driver"); 115 MODULE_LICENSE("GPL"); 116