2 * Second generation of pinmux driver for Amlogic Meson-AXG SoC.
4 * Copyright (c) 2017 Baylibre SAS.
5 * Author: Jerome Brunet <jbrunet@baylibre.com>
7 * Copyright (c) 2017 Amlogic, Inc. All rights reserved.
8 * Author: Xingyu Chen <xingyu.chen@amlogic.com>
10 * SPDX-License-Identifier: (GPL-2.0+ or MIT)
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.
18 * The value 0 is always selecting the GPIO mode, while other
19 * values (start from 1) for selecting the function mode.
21 #include <linux/device.h>
22 #include <linux/regmap.h>
23 #include <linux/pinctrl/pinctrl.h>
24 #include <linux/pinctrl/pinmux.h>
26 #include "pinctrl-meson.h"
27 #include "pinctrl-meson-axg-pmx.h"
29 static int meson_axg_pmx_get_bank(struct meson_pinctrl
*pc
,
31 struct meson_pmx_bank
**bank
)
34 struct meson_axg_pmx_data
*pmx
= pc
->data
->pmx_data
;
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
];
46 static int meson_pmx_calc_reg_and_offset(struct meson_pmx_bank
*bank
,
47 unsigned int pin
, unsigned int *reg
,
52 shift
= pin
- bank
->first
;
54 *reg
= bank
->reg
+ (bank
->offset
+ (shift
<< 2)) / 32;
55 *offset
= (bank
->offset
+ (shift
<< 2)) % 32;
60 static int meson_axg_pmx_update_function(struct meson_pinctrl
*pc
,
61 unsigned int pin
, unsigned int func
)
66 struct meson_pmx_bank
*bank
;
68 ret
= meson_axg_pmx_get_bank(pc
, pin
, &bank
);
72 meson_pmx_calc_reg_and_offset(bank
, pin
, ®
, &offset
);
74 ret
= regmap_update_bits(pc
->reg_mux
, reg
<< 2,
75 0xf << offset
, (func
& 0xf) << offset
);
80 static int meson_axg_pmx_set_mux(struct pinctrl_dev
*pcdev
,
81 unsigned int func_num
, unsigned int group_num
)
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
;
91 dev_dbg(pc
->dev
, "enable function %s, group %s\n", func
->name
,
94 for (i
= 0; i
< group
->num_pins
; i
++) {
95 ret
= meson_axg_pmx_update_function(pc
, group
->pins
[i
],
104 static int meson_axg_pmx_request_gpio(struct pinctrl_dev
*pcdev
,
105 struct pinctrl_gpio_range
*range
, unsigned int offset
)
107 struct meson_pinctrl
*pc
= pinctrl_dev_get_drvdata(pcdev
);
109 return meson_axg_pmx_update_function(pc
, offset
, 0);
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
,
119 EXPORT_SYMBOL_GPL(meson_axg_pmx_ops
);
121 MODULE_LICENSE("Dual BSD/GPL");