Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * First generation of pinmux driver for Amlogic Meson SoCs
0004  *
0005  * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
0006  * Copyright (C) 2017 Jerome Brunet  <jbrunet@baylibre.com>
0007  */
0008 
0009 /* For this first generation of pinctrl driver every pinmux group can be
0010  * enabled by a specific bit in the first register range. When all groups for
0011  * a given pin are disabled the pin acts as a GPIO.
0012  */
0013 #include <linux/device.h>
0014 #include <linux/regmap.h>
0015 #include <linux/pinctrl/pinctrl.h>
0016 #include <linux/pinctrl/pinmux.h>
0017 
0018 #include "pinctrl-meson.h"
0019 #include "pinctrl-meson8-pmx.h"
0020 
0021 /**
0022  * meson8_pmx_disable_other_groups() - disable other groups using a given pin
0023  *
0024  * @pc:     meson pin controller device
0025  * @pin:    number of the pin
0026  * @sel_group:  index of the selected group, or -1 if none
0027  *
0028  * The function disables all pinmux groups using a pin except the
0029  * selected one. If @sel_group is -1 all groups are disabled, leaving
0030  * the pin in GPIO mode.
0031  */
0032 static void meson8_pmx_disable_other_groups(struct meson_pinctrl *pc,
0033                         unsigned int pin, int sel_group)
0034 {
0035     struct meson_pmx_group *group;
0036     struct meson8_pmx_data *pmx_data;
0037     int i, j;
0038 
0039     for (i = 0; i < pc->data->num_groups; i++) {
0040         group = &pc->data->groups[i];
0041         pmx_data = (struct meson8_pmx_data *)group->data;
0042         if (pmx_data->is_gpio || i == sel_group)
0043             continue;
0044 
0045         for (j = 0; j < group->num_pins; j++) {
0046             if (group->pins[j] == pin) {
0047                 /* We have found a group using the pin */
0048                 regmap_update_bits(pc->reg_mux,
0049                            pmx_data->reg * 4,
0050                            BIT(pmx_data->bit), 0);
0051             }
0052         }
0053     }
0054 }
0055 
0056 static int meson8_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned func_num,
0057                   unsigned group_num)
0058 {
0059     struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
0060     struct meson_pmx_func *func = &pc->data->funcs[func_num];
0061     struct meson_pmx_group *group = &pc->data->groups[group_num];
0062     struct meson8_pmx_data *pmx_data =
0063         (struct meson8_pmx_data *)group->data;
0064     int i, ret = 0;
0065 
0066     dev_dbg(pc->dev, "enable function %s, group %s\n", func->name,
0067         group->name);
0068 
0069     /*
0070      * Disable groups using the same pin.
0071      * The selected group is not disabled to avoid glitches.
0072      */
0073     for (i = 0; i < group->num_pins; i++)
0074         meson8_pmx_disable_other_groups(pc, group->pins[i], group_num);
0075 
0076     /* Function 0 (GPIO) doesn't need any additional setting */
0077     if (func_num)
0078         ret = regmap_update_bits(pc->reg_mux, pmx_data->reg * 4,
0079                      BIT(pmx_data->bit),
0080                      BIT(pmx_data->bit));
0081 
0082     return ret;
0083 }
0084 
0085 static int meson8_pmx_request_gpio(struct pinctrl_dev *pcdev,
0086                    struct pinctrl_gpio_range *range,
0087                    unsigned offset)
0088 {
0089     struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
0090 
0091     meson8_pmx_disable_other_groups(pc, offset, -1);
0092 
0093     return 0;
0094 }
0095 
0096 const struct pinmux_ops meson8_pmx_ops = {
0097     .set_mux = meson8_pmx_set_mux,
0098     .get_functions_count = meson_pmx_get_funcs_count,
0099     .get_function_name = meson_pmx_get_func_name,
0100     .get_function_groups = meson_pmx_get_groups,
0101     .gpio_request_enable = meson8_pmx_request_gpio,
0102 };
0103 EXPORT_SYMBOL_GPL(meson8_pmx_ops);
0104 MODULE_LICENSE("GPL v2");