0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include <linux/device.h>
0022 #include <linux/regmap.h>
0023 #include <linux/pinctrl/pinctrl.h>
0024 #include <linux/pinctrl/pinmux.h>
0025
0026 #include "pinctrl-meson.h"
0027 #include "pinctrl-meson-axg-pmx.h"
0028
0029 static int meson_axg_pmx_get_bank(struct meson_pinctrl *pc,
0030 unsigned int pin,
0031 struct meson_pmx_bank **bank)
0032 {
0033 int i;
0034 struct meson_axg_pmx_data *pmx = pc->data->pmx_data;
0035
0036 for (i = 0; i < pmx->num_pmx_banks; i++)
0037 if (pin >= pmx->pmx_banks[i].first &&
0038 pin <= pmx->pmx_banks[i].last) {
0039 *bank = &pmx->pmx_banks[i];
0040 return 0;
0041 }
0042
0043 return -EINVAL;
0044 }
0045
0046 static int meson_pmx_calc_reg_and_offset(struct meson_pmx_bank *bank,
0047 unsigned int pin, unsigned int *reg,
0048 unsigned int *offset)
0049 {
0050 int shift;
0051
0052 shift = pin - bank->first;
0053
0054 *reg = bank->reg + (bank->offset + (shift << 2)) / 32;
0055 *offset = (bank->offset + (shift << 2)) % 32;
0056
0057 return 0;
0058 }
0059
0060 static int meson_axg_pmx_update_function(struct meson_pinctrl *pc,
0061 unsigned int pin, unsigned int func)
0062 {
0063 int ret;
0064 int reg;
0065 int offset;
0066 struct meson_pmx_bank *bank;
0067
0068 ret = meson_axg_pmx_get_bank(pc, pin, &bank);
0069 if (ret)
0070 return ret;
0071
0072 meson_pmx_calc_reg_and_offset(bank, pin, ®, &offset);
0073
0074 ret = regmap_update_bits(pc->reg_mux, reg << 2,
0075 0xf << offset, (func & 0xf) << offset);
0076
0077 return ret;
0078 }
0079
0080 static int meson_axg_pmx_set_mux(struct pinctrl_dev *pcdev,
0081 unsigned int func_num, unsigned int group_num)
0082 {
0083 int i;
0084 int ret;
0085 struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
0086 struct meson_pmx_func *func = &pc->data->funcs[func_num];
0087 struct meson_pmx_group *group = &pc->data->groups[group_num];
0088 struct meson_pmx_axg_data *pmx_data =
0089 (struct meson_pmx_axg_data *)group->data;
0090
0091 dev_dbg(pc->dev, "enable function %s, group %s\n", func->name,
0092 group->name);
0093
0094 for (i = 0; i < group->num_pins; i++) {
0095 ret = meson_axg_pmx_update_function(pc, group->pins[i],
0096 pmx_data->func);
0097 if (ret)
0098 return ret;
0099 }
0100
0101 return 0;
0102 }
0103
0104 static int meson_axg_pmx_request_gpio(struct pinctrl_dev *pcdev,
0105 struct pinctrl_gpio_range *range, unsigned int offset)
0106 {
0107 struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
0108
0109 return meson_axg_pmx_update_function(pc, offset, 0);
0110 }
0111
0112 const struct pinmux_ops meson_axg_pmx_ops = {
0113 .set_mux = meson_axg_pmx_set_mux,
0114 .get_functions_count = meson_pmx_get_funcs_count,
0115 .get_function_name = meson_pmx_get_func_name,
0116 .get_function_groups = meson_pmx_get_groups,
0117 .gpio_request_enable = meson_axg_pmx_request_gpio,
0118 };
0119 EXPORT_SYMBOL_GPL(meson_axg_pmx_ops);
0120
0121 MODULE_LICENSE("Dual BSD/GPL");