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