1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * TLMM driver for Qualcomm APQ8016, APQ8096 4 * 5 * (C) Copyright 2018 Ramon Fried <ramon.fried@gmail.com> 6 * 7 */ 8 9 #include <common.h> 10 #include <dm.h> 11 #include <errno.h> 12 #include <asm/io.h> 13 #include <dm/pinctrl.h> 14 #include "pinctrl-snapdragon.h" 15 16 struct msm_pinctrl_priv { 17 phys_addr_t base; 18 struct msm_pinctrl_data *data; 19 }; 20 21 #define GPIO_CONFIG_OFFSET(x) ((x) * 0x1000) 22 #define TLMM_GPIO_PULL_MASK GENMASK(1, 0) 23 #define TLMM_FUNC_SEL_MASK GENMASK(5, 2) 24 #define TLMM_DRV_STRENGTH_MASK GENMASK(8, 6) 25 #define TLMM_GPIO_DISABLE BIT(9) 26 27 static const struct pinconf_param msm_conf_params[] = { 28 { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 3 }, 29 { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, 30 }; 31 32 static int msm_get_functions_count(struct udevice *dev) 33 { 34 struct msm_pinctrl_priv *priv = dev_get_priv(dev); 35 36 return priv->data->functions_count; 37 } 38 39 static int msm_get_pins_count(struct udevice *dev) 40 { 41 struct msm_pinctrl_priv *priv = dev_get_priv(dev); 42 43 return priv->data->pin_count; 44 } 45 46 static const char *msm_get_function_name(struct udevice *dev, 47 unsigned int selector) 48 { 49 struct msm_pinctrl_priv *priv = dev_get_priv(dev); 50 51 return priv->data->get_function_name(dev, selector); 52 } 53 54 static int msm_pinctrl_probe(struct udevice *dev) 55 { 56 struct msm_pinctrl_priv *priv = dev_get_priv(dev); 57 58 priv->base = devfdt_get_addr(dev); 59 priv->data = (struct msm_pinctrl_data *)dev->driver_data; 60 61 return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0; 62 } 63 64 static const char *msm_get_pin_name(struct udevice *dev, unsigned int selector) 65 { 66 struct msm_pinctrl_priv *priv = dev_get_priv(dev); 67 68 return priv->data->get_pin_name(dev, selector); 69 } 70 71 static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector, 72 unsigned int func_selector) 73 { 74 struct msm_pinctrl_priv *priv = dev_get_priv(dev); 75 76 clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), 77 TLMM_FUNC_SEL_MASK | TLMM_GPIO_DISABLE, 78 priv->data->get_function_mux(func_selector) << 2); 79 return 0; 80 } 81 82 static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector, 83 unsigned int param, unsigned int argument) 84 { 85 struct msm_pinctrl_priv *priv = dev_get_priv(dev); 86 87 switch (param) { 88 case PIN_CONFIG_DRIVE_STRENGTH: 89 clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), 90 TLMM_DRV_STRENGTH_MASK, argument << 6); 91 break; 92 case PIN_CONFIG_BIAS_DISABLE: 93 clrbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), 94 TLMM_GPIO_PULL_MASK); 95 break; 96 default: 97 return 0; 98 } 99 100 return 0; 101 } 102 103 static struct pinctrl_ops msm_pinctrl_ops = { 104 .get_pins_count = msm_get_pins_count, 105 .get_pin_name = msm_get_pin_name, 106 .set_state = pinctrl_generic_set_state, 107 .pinmux_set = msm_pinmux_set, 108 .pinconf_num_params = ARRAY_SIZE(msm_conf_params), 109 .pinconf_params = msm_conf_params, 110 .pinconf_set = msm_pinconf_set, 111 .get_functions_count = msm_get_functions_count, 112 .get_function_name = msm_get_function_name, 113 }; 114 115 static const struct udevice_id msm_pinctrl_ids[] = { 116 { .compatible = "qcom,tlmm-apq8016", .data = (ulong)&apq8016_data }, 117 { .compatible = "qcom,tlmm-apq8096", .data = (ulong)&apq8096_data }, 118 { } 119 }; 120 121 U_BOOT_DRIVER(pinctrl_snapdraon) = { 122 .name = "pinctrl_msm", 123 .id = UCLASS_PINCTRL, 124 .of_match = msm_pinctrl_ids, 125 .priv_auto_alloc_size = sizeof(struct msm_pinctrl_priv), 126 .ops = &msm_pinctrl_ops, 127 .probe = msm_pinctrl_probe, 128 }; 129