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