root/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. meson_axg_pmx_get_bank
  2. meson_pmx_calc_reg_and_offset
  3. meson_axg_pmx_update_function
  4. meson_axg_pmx_set_mux
  5. meson_axg_pmx_request_gpio

   1 /*
   2  * Second generation of pinmux driver for Amlogic Meson-AXG SoC.
   3  *
   4  * Copyright (c) 2017 Baylibre SAS.
   5  * Author:  Jerome Brunet  <jbrunet@baylibre.com>
   6  *
   7  * Copyright (c) 2017 Amlogic, Inc. All rights reserved.
   8  * Author: Xingyu Chen <xingyu.chen@amlogic.com>
   9  *
  10  * SPDX-License-Identifier: (GPL-2.0+ or MIT)
  11  */
  12 
  13 /*
  14  * This new generation of pinctrl IP is mainly adopted by the
  15  * Meson-AXG SoC and later series, which use 4-width continuous
  16  * register bit to select the function for each pin.
  17  *
  18  * The value 0 is always selecting the GPIO mode, while other
  19  * values (start from 1) for selecting the function mode.
  20  */
  21 #include <linux/device.h>
  22 #include <linux/regmap.h>
  23 #include <linux/pinctrl/pinctrl.h>
  24 #include <linux/pinctrl/pinmux.h>
  25 
  26 #include "pinctrl-meson.h"
  27 #include "pinctrl-meson-axg-pmx.h"
  28 
  29 static int meson_axg_pmx_get_bank(struct meson_pinctrl *pc,
  30                         unsigned int pin,
  31                         struct meson_pmx_bank **bank)
  32 {
  33         int i;
  34         struct meson_axg_pmx_data *pmx = pc->data->pmx_data;
  35 
  36         for (i = 0; i < pmx->num_pmx_banks; i++)
  37                 if (pin >= pmx->pmx_banks[i].first &&
  38                                 pin <= pmx->pmx_banks[i].last) {
  39                         *bank = &pmx->pmx_banks[i];
  40                         return 0;
  41                 }
  42 
  43         return -EINVAL;
  44 }
  45 
  46 static int meson_pmx_calc_reg_and_offset(struct meson_pmx_bank *bank,
  47                         unsigned int pin, unsigned int *reg,
  48                         unsigned int *offset)
  49 {
  50         int shift;
  51 
  52         shift = pin - bank->first;
  53 
  54         *reg = bank->reg + (bank->offset + (shift << 2)) / 32;
  55         *offset = (bank->offset + (shift << 2)) % 32;
  56 
  57         return 0;
  58 }
  59 
  60 static int meson_axg_pmx_update_function(struct meson_pinctrl *pc,
  61                         unsigned int pin, unsigned int func)
  62 {
  63         int ret;
  64         int reg;
  65         int offset;
  66         struct meson_pmx_bank *bank;
  67 
  68         ret = meson_axg_pmx_get_bank(pc, pin, &bank);
  69         if (ret)
  70                 return ret;
  71 
  72         meson_pmx_calc_reg_and_offset(bank, pin, &reg, &offset);
  73 
  74         ret = regmap_update_bits(pc->reg_mux, reg << 2,
  75                 0xf << offset, (func & 0xf) << offset);
  76 
  77         return ret;
  78 }
  79 
  80 static int meson_axg_pmx_set_mux(struct pinctrl_dev *pcdev,
  81                         unsigned int func_num, unsigned int group_num)
  82 {
  83         int i;
  84         int ret;
  85         struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
  86         struct meson_pmx_func *func = &pc->data->funcs[func_num];
  87         struct meson_pmx_group *group = &pc->data->groups[group_num];
  88         struct meson_pmx_axg_data *pmx_data =
  89                 (struct meson_pmx_axg_data *)group->data;
  90 
  91         dev_dbg(pc->dev, "enable function %s, group %s\n", func->name,
  92                 group->name);
  93 
  94         for (i = 0; i < group->num_pins; i++) {
  95                 ret = meson_axg_pmx_update_function(pc, group->pins[i],
  96                         pmx_data->func);
  97                 if (ret)
  98                         return ret;
  99         }
 100 
 101         return 0;
 102 }
 103 
 104 static int meson_axg_pmx_request_gpio(struct pinctrl_dev *pcdev,
 105                         struct pinctrl_gpio_range *range, unsigned int offset)
 106 {
 107         struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
 108 
 109         return meson_axg_pmx_update_function(pc, offset, 0);
 110 }
 111 
 112 const struct pinmux_ops meson_axg_pmx_ops = {
 113         .set_mux = meson_axg_pmx_set_mux,
 114         .get_functions_count = meson_pmx_get_funcs_count,
 115         .get_function_name = meson_pmx_get_func_name,
 116         .get_function_groups = meson_pmx_get_groups,
 117         .gpio_request_enable = meson_axg_pmx_request_gpio,
 118 };

/* [<][>][^][v][top][bottom][index][help] */