Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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