18b242ca7SSai Krishna Potthuri // SPDX-License-Identifier: GPL-2.0 28b242ca7SSai Krishna Potthuri /* 38b242ca7SSai Krishna Potthuri * ZynqMP pin controller 48b242ca7SSai Krishna Potthuri * 5fa99e701SSai Krishna Potthuri * Copyright (C) 2020, 2021 Xilinx, Inc. 68b242ca7SSai Krishna Potthuri * 78b242ca7SSai Krishna Potthuri * Sai Krishna Potthuri <lakshmi.sai.krishna.potthuri@xilinx.com> 88b242ca7SSai Krishna Potthuri * Rajan Vaja <rajan.vaja@xilinx.com> 98b242ca7SSai Krishna Potthuri */ 108b242ca7SSai Krishna Potthuri 118b242ca7SSai Krishna Potthuri #include <dt-bindings/pinctrl/pinctrl-zynqmp.h> 128b242ca7SSai Krishna Potthuri 13*f28cbab9SSean Anderson #include <linux/bitmap.h> 148b242ca7SSai Krishna Potthuri #include <linux/init.h> 158b242ca7SSai Krishna Potthuri #include <linux/module.h> 168b242ca7SSai Krishna Potthuri #include <linux/of_address.h> 178b242ca7SSai Krishna Potthuri #include <linux/platform_device.h> 18e9d10adcSAndy Shevchenko 198b242ca7SSai Krishna Potthuri #include <linux/firmware/xlnx-zynqmp.h> 208b242ca7SSai Krishna Potthuri 218b242ca7SSai Krishna Potthuri #include <linux/pinctrl/pinconf-generic.h> 22e9d10adcSAndy Shevchenko #include <linux/pinctrl/pinconf.h> 23e9d10adcSAndy Shevchenko #include <linux/pinctrl/pinctrl.h> 24e9d10adcSAndy Shevchenko #include <linux/pinctrl/pinmux.h> 258b242ca7SSai Krishna Potthuri 268b242ca7SSai Krishna Potthuri #include "core.h" 278b242ca7SSai Krishna Potthuri #include "pinctrl-utils.h" 288b242ca7SSai Krishna Potthuri 298b242ca7SSai Krishna Potthuri #define ZYNQMP_PIN_PREFIX "MIO" 308b242ca7SSai Krishna Potthuri #define PINCTRL_GET_FUNC_NAME_RESP_LEN 16 318b242ca7SSai Krishna Potthuri #define MAX_FUNC_NAME_LEN 16 328b242ca7SSai Krishna Potthuri #define MAX_GROUP_PIN 50 338b242ca7SSai Krishna Potthuri #define MAX_PIN_GROUPS 50 348b242ca7SSai Krishna Potthuri #define END_OF_FUNCTIONS "END_OF_FUNCTIONS" 358b242ca7SSai Krishna Potthuri #define NUM_GROUPS_PER_RESP 6 368b242ca7SSai Krishna Potthuri 378b242ca7SSai Krishna Potthuri #define PINCTRL_GET_FUNC_GROUPS_RESP_LEN 12 388b242ca7SSai Krishna Potthuri #define PINCTRL_GET_PIN_GROUPS_RESP_LEN 12 398b242ca7SSai Krishna Potthuri #define NA_GROUP 0xFFFF 408b242ca7SSai Krishna Potthuri #define RESERVED_GROUP 0xFFFE 418b242ca7SSai Krishna Potthuri 428b242ca7SSai Krishna Potthuri #define DRIVE_STRENGTH_2MA 2 438b242ca7SSai Krishna Potthuri #define DRIVE_STRENGTH_4MA 4 448b242ca7SSai Krishna Potthuri #define DRIVE_STRENGTH_8MA 8 458b242ca7SSai Krishna Potthuri #define DRIVE_STRENGTH_12MA 12 468b242ca7SSai Krishna Potthuri 478b242ca7SSai Krishna Potthuri /** 488b242ca7SSai Krishna Potthuri * struct zynqmp_pmux_function - a pinmux function 498b242ca7SSai Krishna Potthuri * @name: Name of the pin mux function 508b242ca7SSai Krishna Potthuri * @groups: List of pin groups for this function 518b242ca7SSai Krishna Potthuri * @ngroups: Number of entries in @groups 528b242ca7SSai Krishna Potthuri * @node: Firmware node matching with the function 538b242ca7SSai Krishna Potthuri * 548b242ca7SSai Krishna Potthuri * This structure holds information about pin control function 558b242ca7SSai Krishna Potthuri * and function group names supporting that function. 568b242ca7SSai Krishna Potthuri */ 578b242ca7SSai Krishna Potthuri struct zynqmp_pmux_function { 588b242ca7SSai Krishna Potthuri char name[MAX_FUNC_NAME_LEN]; 598b242ca7SSai Krishna Potthuri const char * const *groups; 608b242ca7SSai Krishna Potthuri unsigned int ngroups; 618b242ca7SSai Krishna Potthuri }; 628b242ca7SSai Krishna Potthuri 638b242ca7SSai Krishna Potthuri /** 648b242ca7SSai Krishna Potthuri * struct zynqmp_pinctrl - driver data 658b242ca7SSai Krishna Potthuri * @pctrl: Pin control device 668b242ca7SSai Krishna Potthuri * @groups: Pin groups 678b242ca7SSai Krishna Potthuri * @ngroups: Number of @groups 688b242ca7SSai Krishna Potthuri * @funcs: Pin mux functions 698b242ca7SSai Krishna Potthuri * @nfuncs: Number of @funcs 708b242ca7SSai Krishna Potthuri * 718b242ca7SSai Krishna Potthuri * This struct is stored as driver data and used to retrieve 728b242ca7SSai Krishna Potthuri * information regarding pin control functions, groups and 738b242ca7SSai Krishna Potthuri * group pins. 748b242ca7SSai Krishna Potthuri */ 758b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl { 768b242ca7SSai Krishna Potthuri struct pinctrl_dev *pctrl; 778b242ca7SSai Krishna Potthuri const struct zynqmp_pctrl_group *groups; 788b242ca7SSai Krishna Potthuri unsigned int ngroups; 798b242ca7SSai Krishna Potthuri const struct zynqmp_pmux_function *funcs; 808b242ca7SSai Krishna Potthuri unsigned int nfuncs; 818b242ca7SSai Krishna Potthuri }; 828b242ca7SSai Krishna Potthuri 838b242ca7SSai Krishna Potthuri /** 848b242ca7SSai Krishna Potthuri * struct zynqmp_pctrl_group - Pin control group info 858b242ca7SSai Krishna Potthuri * @name: Group name 868b242ca7SSai Krishna Potthuri * @pins: Group pin numbers 878b242ca7SSai Krishna Potthuri * @npins: Number of pins in the group 888b242ca7SSai Krishna Potthuri */ 898b242ca7SSai Krishna Potthuri struct zynqmp_pctrl_group { 908b242ca7SSai Krishna Potthuri const char *name; 918b242ca7SSai Krishna Potthuri unsigned int pins[MAX_GROUP_PIN]; 928b242ca7SSai Krishna Potthuri unsigned int npins; 938b242ca7SSai Krishna Potthuri }; 948b242ca7SSai Krishna Potthuri 958b242ca7SSai Krishna Potthuri static struct pinctrl_desc zynqmp_desc; 968b242ca7SSai Krishna Potthuri 978b242ca7SSai Krishna Potthuri static int zynqmp_pctrl_get_groups_count(struct pinctrl_dev *pctldev) 988b242ca7SSai Krishna Potthuri { 998b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 1008b242ca7SSai Krishna Potthuri 101*f28cbab9SSean Anderson return pctrl->ngroups + zynqmp_desc.npins; 1028b242ca7SSai Krishna Potthuri } 1038b242ca7SSai Krishna Potthuri 1048b242ca7SSai Krishna Potthuri static const char *zynqmp_pctrl_get_group_name(struct pinctrl_dev *pctldev, 1058b242ca7SSai Krishna Potthuri unsigned int selector) 1068b242ca7SSai Krishna Potthuri { 1078b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 1088b242ca7SSai Krishna Potthuri 109*f28cbab9SSean Anderson if (selector < pctrl->ngroups) 1108b242ca7SSai Krishna Potthuri return pctrl->groups[selector].name; 111*f28cbab9SSean Anderson 112*f28cbab9SSean Anderson return zynqmp_desc.pins[selector - pctrl->ngroups].name; 1138b242ca7SSai Krishna Potthuri } 1148b242ca7SSai Krishna Potthuri 1158b242ca7SSai Krishna Potthuri static int zynqmp_pctrl_get_group_pins(struct pinctrl_dev *pctldev, 1168b242ca7SSai Krishna Potthuri unsigned int selector, 1178b242ca7SSai Krishna Potthuri const unsigned int **pins, 1188b242ca7SSai Krishna Potthuri unsigned int *npins) 1198b242ca7SSai Krishna Potthuri { 1208b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 1218b242ca7SSai Krishna Potthuri 122*f28cbab9SSean Anderson if (selector < pctrl->ngroups) { 1238b242ca7SSai Krishna Potthuri *pins = pctrl->groups[selector].pins; 1248b242ca7SSai Krishna Potthuri *npins = pctrl->groups[selector].npins; 125*f28cbab9SSean Anderson } else { 126*f28cbab9SSean Anderson *pins = &zynqmp_desc.pins[selector - pctrl->ngroups].number; 127*f28cbab9SSean Anderson *npins = 1; 128*f28cbab9SSean Anderson } 1298b242ca7SSai Krishna Potthuri 1308b242ca7SSai Krishna Potthuri return 0; 1318b242ca7SSai Krishna Potthuri } 1328b242ca7SSai Krishna Potthuri 1338b242ca7SSai Krishna Potthuri static const struct pinctrl_ops zynqmp_pctrl_ops = { 1348b242ca7SSai Krishna Potthuri .get_groups_count = zynqmp_pctrl_get_groups_count, 1358b242ca7SSai Krishna Potthuri .get_group_name = zynqmp_pctrl_get_group_name, 1368b242ca7SSai Krishna Potthuri .get_group_pins = zynqmp_pctrl_get_group_pins, 1378b242ca7SSai Krishna Potthuri .dt_node_to_map = pinconf_generic_dt_node_to_map_all, 1388b242ca7SSai Krishna Potthuri .dt_free_map = pinctrl_utils_free_map, 1398b242ca7SSai Krishna Potthuri }; 1408b242ca7SSai Krishna Potthuri 1418b242ca7SSai Krishna Potthuri static int zynqmp_pinmux_request_pin(struct pinctrl_dev *pctldev, 1428b242ca7SSai Krishna Potthuri unsigned int pin) 1438b242ca7SSai Krishna Potthuri { 1448b242ca7SSai Krishna Potthuri int ret; 1458b242ca7SSai Krishna Potthuri 1468b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_request(pin); 1478b242ca7SSai Krishna Potthuri if (ret) { 1488b242ca7SSai Krishna Potthuri dev_err(pctldev->dev, "request failed for pin %u\n", pin); 1498b242ca7SSai Krishna Potthuri return ret; 1508b242ca7SSai Krishna Potthuri } 1518b242ca7SSai Krishna Potthuri 1528b242ca7SSai Krishna Potthuri return 0; 1538b242ca7SSai Krishna Potthuri } 1548b242ca7SSai Krishna Potthuri 1558b242ca7SSai Krishna Potthuri static int zynqmp_pmux_get_functions_count(struct pinctrl_dev *pctldev) 1568b242ca7SSai Krishna Potthuri { 1578b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 1588b242ca7SSai Krishna Potthuri 1598b242ca7SSai Krishna Potthuri return pctrl->nfuncs; 1608b242ca7SSai Krishna Potthuri } 1618b242ca7SSai Krishna Potthuri 1628b242ca7SSai Krishna Potthuri static const char *zynqmp_pmux_get_function_name(struct pinctrl_dev *pctldev, 1638b242ca7SSai Krishna Potthuri unsigned int selector) 1648b242ca7SSai Krishna Potthuri { 1658b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 1668b242ca7SSai Krishna Potthuri 1678b242ca7SSai Krishna Potthuri return pctrl->funcs[selector].name; 1688b242ca7SSai Krishna Potthuri } 1698b242ca7SSai Krishna Potthuri 1708b242ca7SSai Krishna Potthuri /** 1718b242ca7SSai Krishna Potthuri * zynqmp_pmux_get_function_groups() - Get groups for the function 1728b242ca7SSai Krishna Potthuri * @pctldev: Pincontrol device pointer. 1738b242ca7SSai Krishna Potthuri * @selector: Function ID 1748b242ca7SSai Krishna Potthuri * @groups: Group names. 1758b242ca7SSai Krishna Potthuri * @num_groups: Number of function groups. 1768b242ca7SSai Krishna Potthuri * 1778b242ca7SSai Krishna Potthuri * Get function's group count and group names. 178eb1c38c6SSai Krishna Potthuri * 179eb1c38c6SSai Krishna Potthuri * Return: 0 1808b242ca7SSai Krishna Potthuri */ 1818b242ca7SSai Krishna Potthuri static int zynqmp_pmux_get_function_groups(struct pinctrl_dev *pctldev, 1828b242ca7SSai Krishna Potthuri unsigned int selector, 1838b242ca7SSai Krishna Potthuri const char * const **groups, 1848b242ca7SSai Krishna Potthuri unsigned * const num_groups) 1858b242ca7SSai Krishna Potthuri { 1868b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 1878b242ca7SSai Krishna Potthuri 1888b242ca7SSai Krishna Potthuri *groups = pctrl->funcs[selector].groups; 1898b242ca7SSai Krishna Potthuri *num_groups = pctrl->funcs[selector].ngroups; 1908b242ca7SSai Krishna Potthuri 1918b242ca7SSai Krishna Potthuri return 0; 1928b242ca7SSai Krishna Potthuri } 1938b242ca7SSai Krishna Potthuri 1948b242ca7SSai Krishna Potthuri /** 1958b242ca7SSai Krishna Potthuri * zynqmp_pinmux_set_mux() - Set requested function for the group 1968b242ca7SSai Krishna Potthuri * @pctldev: Pincontrol device pointer. 1978b242ca7SSai Krishna Potthuri * @function: Function ID. 1988b242ca7SSai Krishna Potthuri * @group: Group ID. 1998b242ca7SSai Krishna Potthuri * 2008b242ca7SSai Krishna Potthuri * Loop through all pins of the group and call firmware API 2018b242ca7SSai Krishna Potthuri * to set requested function for all pins in the group. 2028b242ca7SSai Krishna Potthuri * 2038b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 2048b242ca7SSai Krishna Potthuri */ 2058b242ca7SSai Krishna Potthuri static int zynqmp_pinmux_set_mux(struct pinctrl_dev *pctldev, 2068b242ca7SSai Krishna Potthuri unsigned int function, 2078b242ca7SSai Krishna Potthuri unsigned int group) 2088b242ca7SSai Krishna Potthuri { 209*f28cbab9SSean Anderson const unsigned int *pins; 210*f28cbab9SSean Anderson unsigned int npins; 2118b242ca7SSai Krishna Potthuri int ret, i; 2128b242ca7SSai Krishna Potthuri 213*f28cbab9SSean Anderson zynqmp_pctrl_get_group_pins(pctldev, group, &pins, &npins); 214*f28cbab9SSean Anderson for (i = 0; i < npins; i++) { 215*f28cbab9SSean Anderson ret = zynqmp_pm_pinctrl_set_function(pins[i], function); 2168b242ca7SSai Krishna Potthuri if (ret) { 2178b242ca7SSai Krishna Potthuri dev_err(pctldev->dev, "set mux failed for pin %u\n", 218*f28cbab9SSean Anderson pins[i]); 2198b242ca7SSai Krishna Potthuri return ret; 2208b242ca7SSai Krishna Potthuri } 2218b242ca7SSai Krishna Potthuri } 2228b242ca7SSai Krishna Potthuri 2238b242ca7SSai Krishna Potthuri return 0; 2248b242ca7SSai Krishna Potthuri } 2258b242ca7SSai Krishna Potthuri 2268b242ca7SSai Krishna Potthuri static int zynqmp_pinmux_release_pin(struct pinctrl_dev *pctldev, 2278b242ca7SSai Krishna Potthuri unsigned int pin) 2288b242ca7SSai Krishna Potthuri { 2298b242ca7SSai Krishna Potthuri int ret; 2308b242ca7SSai Krishna Potthuri 2318b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_release(pin); 2328b242ca7SSai Krishna Potthuri if (ret) { 2338b242ca7SSai Krishna Potthuri dev_err(pctldev->dev, "free pin failed for pin %u\n", 2348b242ca7SSai Krishna Potthuri pin); 2358b242ca7SSai Krishna Potthuri return ret; 2368b242ca7SSai Krishna Potthuri } 2378b242ca7SSai Krishna Potthuri 2388b242ca7SSai Krishna Potthuri return 0; 2398b242ca7SSai Krishna Potthuri } 2408b242ca7SSai Krishna Potthuri 2418b242ca7SSai Krishna Potthuri static const struct pinmux_ops zynqmp_pinmux_ops = { 2428b242ca7SSai Krishna Potthuri .request = zynqmp_pinmux_request_pin, 2438b242ca7SSai Krishna Potthuri .get_functions_count = zynqmp_pmux_get_functions_count, 2448b242ca7SSai Krishna Potthuri .get_function_name = zynqmp_pmux_get_function_name, 2458b242ca7SSai Krishna Potthuri .get_function_groups = zynqmp_pmux_get_function_groups, 2468b242ca7SSai Krishna Potthuri .set_mux = zynqmp_pinmux_set_mux, 2478b242ca7SSai Krishna Potthuri .free = zynqmp_pinmux_release_pin, 2488b242ca7SSai Krishna Potthuri }; 2498b242ca7SSai Krishna Potthuri 2508b242ca7SSai Krishna Potthuri /** 2518b242ca7SSai Krishna Potthuri * zynqmp_pinconf_cfg_get() - get config value for the pin 2528b242ca7SSai Krishna Potthuri * @pctldev: Pin control device pointer. 2538b242ca7SSai Krishna Potthuri * @pin: Pin number. 2548b242ca7SSai Krishna Potthuri * @config: Value of config param. 2558b242ca7SSai Krishna Potthuri * 2568b242ca7SSai Krishna Potthuri * Get value of the requested configuration parameter for the 2578b242ca7SSai Krishna Potthuri * given pin. 2588b242ca7SSai Krishna Potthuri * 2598b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 2608b242ca7SSai Krishna Potthuri */ 2618b242ca7SSai Krishna Potthuri static int zynqmp_pinconf_cfg_get(struct pinctrl_dev *pctldev, 2628b242ca7SSai Krishna Potthuri unsigned int pin, 2638b242ca7SSai Krishna Potthuri unsigned long *config) 2648b242ca7SSai Krishna Potthuri { 2658b242ca7SSai Krishna Potthuri unsigned int arg, param = pinconf_to_config_param(*config); 2668b242ca7SSai Krishna Potthuri int ret; 2678b242ca7SSai Krishna Potthuri 2688b242ca7SSai Krishna Potthuri switch (param) { 2698b242ca7SSai Krishna Potthuri case PIN_CONFIG_SLEW_RATE: 2708b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_SLEW_RATE; 2718b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 2728b242ca7SSai Krishna Potthuri break; 2738b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_PULL_UP: 2748b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_PULL_CTRL; 2758b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 2768b242ca7SSai Krishna Potthuri if (arg != PM_PINCTRL_BIAS_PULL_UP) 2778b242ca7SSai Krishna Potthuri return -EINVAL; 2788b242ca7SSai Krishna Potthuri 2798b242ca7SSai Krishna Potthuri arg = 1; 2808b242ca7SSai Krishna Potthuri break; 2818b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_PULL_DOWN: 2828b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_PULL_CTRL; 2838b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 2848b242ca7SSai Krishna Potthuri if (arg != PM_PINCTRL_BIAS_PULL_DOWN) 2858b242ca7SSai Krishna Potthuri return -EINVAL; 2868b242ca7SSai Krishna Potthuri 2878b242ca7SSai Krishna Potthuri arg = 1; 2888b242ca7SSai Krishna Potthuri break; 2898b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_DISABLE: 2908b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_BIAS_STATUS; 2918b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 2928b242ca7SSai Krishna Potthuri if (arg != PM_PINCTRL_BIAS_DISABLE) 2938b242ca7SSai Krishna Potthuri return -EINVAL; 2948b242ca7SSai Krishna Potthuri 2958b242ca7SSai Krishna Potthuri arg = 1; 2968b242ca7SSai Krishna Potthuri break; 2978b242ca7SSai Krishna Potthuri case PIN_CONFIG_POWER_SOURCE: 2988b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; 2998b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 3008b242ca7SSai Krishna Potthuri break; 3018b242ca7SSai Krishna Potthuri case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 3028b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_SCHMITT_CMOS; 3038b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 3048b242ca7SSai Krishna Potthuri break; 3058b242ca7SSai Krishna Potthuri case PIN_CONFIG_DRIVE_STRENGTH: 3068b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH; 3078b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 3088b242ca7SSai Krishna Potthuri switch (arg) { 3098b242ca7SSai Krishna Potthuri case PM_PINCTRL_DRIVE_STRENGTH_2MA: 3108b242ca7SSai Krishna Potthuri arg = DRIVE_STRENGTH_2MA; 3118b242ca7SSai Krishna Potthuri break; 3128b242ca7SSai Krishna Potthuri case PM_PINCTRL_DRIVE_STRENGTH_4MA: 3138b242ca7SSai Krishna Potthuri arg = DRIVE_STRENGTH_4MA; 3148b242ca7SSai Krishna Potthuri break; 3158b242ca7SSai Krishna Potthuri case PM_PINCTRL_DRIVE_STRENGTH_8MA: 3168b242ca7SSai Krishna Potthuri arg = DRIVE_STRENGTH_8MA; 3178b242ca7SSai Krishna Potthuri break; 3188b242ca7SSai Krishna Potthuri case PM_PINCTRL_DRIVE_STRENGTH_12MA: 3198b242ca7SSai Krishna Potthuri arg = DRIVE_STRENGTH_12MA; 3208b242ca7SSai Krishna Potthuri break; 3218b242ca7SSai Krishna Potthuri default: 3228b242ca7SSai Krishna Potthuri /* Invalid drive strength */ 3238b242ca7SSai Krishna Potthuri dev_warn(pctldev->dev, 3248b242ca7SSai Krishna Potthuri "Invalid drive strength for pin %d\n", 3258b242ca7SSai Krishna Potthuri pin); 3268b242ca7SSai Krishna Potthuri return -EINVAL; 3278b242ca7SSai Krishna Potthuri } 3288b242ca7SSai Krishna Potthuri break; 3298b242ca7SSai Krishna Potthuri default: 330fa99e701SSai Krishna Potthuri ret = -ENOTSUPP; 3318b242ca7SSai Krishna Potthuri break; 3328b242ca7SSai Krishna Potthuri } 3338b242ca7SSai Krishna Potthuri 3348b242ca7SSai Krishna Potthuri if (ret) 3358b242ca7SSai Krishna Potthuri return ret; 3368b242ca7SSai Krishna Potthuri 3378b242ca7SSai Krishna Potthuri param = pinconf_to_config_param(*config); 3388b242ca7SSai Krishna Potthuri *config = pinconf_to_config_packed(param, arg); 3398b242ca7SSai Krishna Potthuri 3408b242ca7SSai Krishna Potthuri return 0; 3418b242ca7SSai Krishna Potthuri } 3428b242ca7SSai Krishna Potthuri 3438b242ca7SSai Krishna Potthuri /** 3448b242ca7SSai Krishna Potthuri * zynqmp_pinconf_cfg_set() - Set requested config for the pin 3458b242ca7SSai Krishna Potthuri * @pctldev: Pincontrol device pointer. 3468b242ca7SSai Krishna Potthuri * @pin: Pin number. 3478b242ca7SSai Krishna Potthuri * @configs: Configuration to set. 3488b242ca7SSai Krishna Potthuri * @num_configs: Number of configurations. 3498b242ca7SSai Krishna Potthuri * 3508b242ca7SSai Krishna Potthuri * Loop through all configurations and call firmware API 3518b242ca7SSai Krishna Potthuri * to set requested configurations for the pin. 3528b242ca7SSai Krishna Potthuri * 3538b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 3548b242ca7SSai Krishna Potthuri */ 3558b242ca7SSai Krishna Potthuri static int zynqmp_pinconf_cfg_set(struct pinctrl_dev *pctldev, 3568b242ca7SSai Krishna Potthuri unsigned int pin, unsigned long *configs, 3578b242ca7SSai Krishna Potthuri unsigned int num_configs) 3588b242ca7SSai Krishna Potthuri { 3598b242ca7SSai Krishna Potthuri int i, ret; 3608b242ca7SSai Krishna Potthuri 3618b242ca7SSai Krishna Potthuri for (i = 0; i < num_configs; i++) { 3628b242ca7SSai Krishna Potthuri unsigned int param = pinconf_to_config_param(configs[i]); 3638b242ca7SSai Krishna Potthuri unsigned int arg = pinconf_to_config_argument(configs[i]); 3648b242ca7SSai Krishna Potthuri unsigned int value; 3658b242ca7SSai Krishna Potthuri 3668b242ca7SSai Krishna Potthuri switch (param) { 3678b242ca7SSai Krishna Potthuri case PIN_CONFIG_SLEW_RATE: 3688b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_SLEW_RATE; 3698b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 3708b242ca7SSai Krishna Potthuri break; 3718b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_PULL_UP: 3728b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_PULL_CTRL; 3738b242ca7SSai Krishna Potthuri arg = PM_PINCTRL_BIAS_PULL_UP; 3748b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 3758b242ca7SSai Krishna Potthuri break; 3768b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_PULL_DOWN: 3778b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_PULL_CTRL; 3788b242ca7SSai Krishna Potthuri arg = PM_PINCTRL_BIAS_PULL_DOWN; 3798b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 3808b242ca7SSai Krishna Potthuri break; 3818b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_DISABLE: 3828b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_BIAS_STATUS; 3838b242ca7SSai Krishna Potthuri arg = PM_PINCTRL_BIAS_DISABLE; 3848b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 3858b242ca7SSai Krishna Potthuri break; 3868b242ca7SSai Krishna Potthuri case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 3878b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_SCHMITT_CMOS; 3888b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 3898b242ca7SSai Krishna Potthuri break; 3908b242ca7SSai Krishna Potthuri case PIN_CONFIG_DRIVE_STRENGTH: 3918b242ca7SSai Krishna Potthuri switch (arg) { 3928b242ca7SSai Krishna Potthuri case DRIVE_STRENGTH_2MA: 3938b242ca7SSai Krishna Potthuri value = PM_PINCTRL_DRIVE_STRENGTH_2MA; 3948b242ca7SSai Krishna Potthuri break; 3958b242ca7SSai Krishna Potthuri case DRIVE_STRENGTH_4MA: 3968b242ca7SSai Krishna Potthuri value = PM_PINCTRL_DRIVE_STRENGTH_4MA; 3978b242ca7SSai Krishna Potthuri break; 3988b242ca7SSai Krishna Potthuri case DRIVE_STRENGTH_8MA: 3998b242ca7SSai Krishna Potthuri value = PM_PINCTRL_DRIVE_STRENGTH_8MA; 4008b242ca7SSai Krishna Potthuri break; 4018b242ca7SSai Krishna Potthuri case DRIVE_STRENGTH_12MA: 4028b242ca7SSai Krishna Potthuri value = PM_PINCTRL_DRIVE_STRENGTH_12MA; 4038b242ca7SSai Krishna Potthuri break; 4048b242ca7SSai Krishna Potthuri default: 4058b242ca7SSai Krishna Potthuri /* Invalid drive strength */ 4068b242ca7SSai Krishna Potthuri dev_warn(pctldev->dev, 4078b242ca7SSai Krishna Potthuri "Invalid drive strength for pin %d\n", 4088b242ca7SSai Krishna Potthuri pin); 4098b242ca7SSai Krishna Potthuri return -EINVAL; 4108b242ca7SSai Krishna Potthuri } 4118b242ca7SSai Krishna Potthuri 4128b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH; 4138b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, value); 4148b242ca7SSai Krishna Potthuri break; 4158b242ca7SSai Krishna Potthuri case PIN_CONFIG_POWER_SOURCE: 4168b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; 4178b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &value); 4188b242ca7SSai Krishna Potthuri 4198b242ca7SSai Krishna Potthuri if (arg != value) 4208b242ca7SSai Krishna Potthuri dev_warn(pctldev->dev, 4218b242ca7SSai Krishna Potthuri "Invalid IO Standard requested for pin %d\n", 4228b242ca7SSai Krishna Potthuri pin); 4238b242ca7SSai Krishna Potthuri 4248b242ca7SSai Krishna Potthuri break; 4258b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: 4260516dd65SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_TRI_STATE; 4270516dd65SSai Krishna Potthuri arg = PM_PINCTRL_TRI_STATE_ENABLE; 4280516dd65SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 4290516dd65SSai Krishna Potthuri break; 4308b242ca7SSai Krishna Potthuri case PIN_CONFIG_MODE_LOW_POWER: 4318b242ca7SSai Krishna Potthuri /* 4328b242ca7SSai Krishna Potthuri * These cases are mentioned in dts but configurable 4338b242ca7SSai Krishna Potthuri * registers are unknown. So falling through to ignore 4348b242ca7SSai Krishna Potthuri * boot time warnings as of now. 4358b242ca7SSai Krishna Potthuri */ 4368b242ca7SSai Krishna Potthuri ret = 0; 4378b242ca7SSai Krishna Potthuri break; 4380516dd65SSai Krishna Potthuri case PIN_CONFIG_OUTPUT_ENABLE: 4390516dd65SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_TRI_STATE; 4400516dd65SSai Krishna Potthuri arg = PM_PINCTRL_TRI_STATE_DISABLE; 4410516dd65SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 4420516dd65SSai Krishna Potthuri break; 4438b242ca7SSai Krishna Potthuri default: 4448b242ca7SSai Krishna Potthuri dev_warn(pctldev->dev, 4458b242ca7SSai Krishna Potthuri "unsupported configuration parameter '%u'\n", 4468b242ca7SSai Krishna Potthuri param); 447fa99e701SSai Krishna Potthuri ret = -ENOTSUPP; 4488b242ca7SSai Krishna Potthuri break; 4498b242ca7SSai Krishna Potthuri } 4508b242ca7SSai Krishna Potthuri 4518b242ca7SSai Krishna Potthuri param = pinconf_to_config_param(configs[i]); 4528b242ca7SSai Krishna Potthuri arg = pinconf_to_config_argument(configs[i]); 4538b242ca7SSai Krishna Potthuri if (ret) 4548b242ca7SSai Krishna Potthuri dev_warn(pctldev->dev, 4558b242ca7SSai Krishna Potthuri "failed to set: pin %u param %u value %u\n", 4568b242ca7SSai Krishna Potthuri pin, param, arg); 4578b242ca7SSai Krishna Potthuri } 4588b242ca7SSai Krishna Potthuri 4598b242ca7SSai Krishna Potthuri return 0; 4608b242ca7SSai Krishna Potthuri } 4618b242ca7SSai Krishna Potthuri 4628b242ca7SSai Krishna Potthuri /** 4638b242ca7SSai Krishna Potthuri * zynqmp_pinconf_group_set() - Set requested config for the group 4648b242ca7SSai Krishna Potthuri * @pctldev: Pincontrol device pointer. 4658b242ca7SSai Krishna Potthuri * @selector: Group ID. 4668b242ca7SSai Krishna Potthuri * @configs: Configuration to set. 4678b242ca7SSai Krishna Potthuri * @num_configs: Number of configurations. 4688b242ca7SSai Krishna Potthuri * 4698b242ca7SSai Krishna Potthuri * Call function to set configs for each pin in the group. 4708b242ca7SSai Krishna Potthuri * 4718b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 4728b242ca7SSai Krishna Potthuri */ 4738b242ca7SSai Krishna Potthuri static int zynqmp_pinconf_group_set(struct pinctrl_dev *pctldev, 4748b242ca7SSai Krishna Potthuri unsigned int selector, 4758b242ca7SSai Krishna Potthuri unsigned long *configs, 4768b242ca7SSai Krishna Potthuri unsigned int num_configs) 4778b242ca7SSai Krishna Potthuri { 478*f28cbab9SSean Anderson const unsigned int *pins; 479*f28cbab9SSean Anderson unsigned int npins; 4808b242ca7SSai Krishna Potthuri int i, ret; 4818b242ca7SSai Krishna Potthuri 482*f28cbab9SSean Anderson zynqmp_pctrl_get_group_pins(pctldev, selector, &pins, &npins); 483*f28cbab9SSean Anderson for (i = 0; i < npins; i++) { 484*f28cbab9SSean Anderson ret = zynqmp_pinconf_cfg_set(pctldev, pins[i], configs, 4858b242ca7SSai Krishna Potthuri num_configs); 4868b242ca7SSai Krishna Potthuri if (ret) 4878b242ca7SSai Krishna Potthuri return ret; 4888b242ca7SSai Krishna Potthuri } 4898b242ca7SSai Krishna Potthuri 4908b242ca7SSai Krishna Potthuri return 0; 4918b242ca7SSai Krishna Potthuri } 4928b242ca7SSai Krishna Potthuri 4938b242ca7SSai Krishna Potthuri static const struct pinconf_ops zynqmp_pinconf_ops = { 4948b242ca7SSai Krishna Potthuri .is_generic = true, 4958b242ca7SSai Krishna Potthuri .pin_config_get = zynqmp_pinconf_cfg_get, 4968b242ca7SSai Krishna Potthuri .pin_config_set = zynqmp_pinconf_cfg_set, 4978b242ca7SSai Krishna Potthuri .pin_config_group_set = zynqmp_pinconf_group_set, 4988b242ca7SSai Krishna Potthuri }; 4998b242ca7SSai Krishna Potthuri 5008b242ca7SSai Krishna Potthuri static struct pinctrl_desc zynqmp_desc = { 5018b242ca7SSai Krishna Potthuri .name = "zynqmp_pinctrl", 5028b242ca7SSai Krishna Potthuri .owner = THIS_MODULE, 5038b242ca7SSai Krishna Potthuri .pctlops = &zynqmp_pctrl_ops, 5048b242ca7SSai Krishna Potthuri .pmxops = &zynqmp_pinmux_ops, 5058b242ca7SSai Krishna Potthuri .confops = &zynqmp_pinconf_ops, 5068b242ca7SSai Krishna Potthuri }; 5078b242ca7SSai Krishna Potthuri 5088b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_get_function_groups(u32 fid, u32 index, u16 *groups) 5098b242ca7SSai Krishna Potthuri { 5108b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 5118b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 5128b242ca7SSai Krishna Potthuri int ret; 5138b242ca7SSai Krishna Potthuri 5148b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_FUNCTION_GROUPS; 5158b242ca7SSai Krishna Potthuri qdata.arg1 = fid; 5168b242ca7SSai Krishna Potthuri qdata.arg2 = index; 5178b242ca7SSai Krishna Potthuri 5188b242ca7SSai Krishna Potthuri ret = zynqmp_pm_query_data(qdata, payload); 5198b242ca7SSai Krishna Potthuri if (ret) 5208b242ca7SSai Krishna Potthuri return ret; 5218b242ca7SSai Krishna Potthuri 5228b242ca7SSai Krishna Potthuri memcpy(groups, &payload[1], PINCTRL_GET_FUNC_GROUPS_RESP_LEN); 5238b242ca7SSai Krishna Potthuri 524fa99e701SSai Krishna Potthuri return 0; 5258b242ca7SSai Krishna Potthuri } 5268b242ca7SSai Krishna Potthuri 5278b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_get_func_num_groups(u32 fid, unsigned int *ngroups) 5288b242ca7SSai Krishna Potthuri { 5298b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 5308b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 5318b242ca7SSai Krishna Potthuri int ret; 5328b242ca7SSai Krishna Potthuri 5338b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS; 5348b242ca7SSai Krishna Potthuri qdata.arg1 = fid; 5358b242ca7SSai Krishna Potthuri 5368b242ca7SSai Krishna Potthuri ret = zynqmp_pm_query_data(qdata, payload); 5378b242ca7SSai Krishna Potthuri if (ret) 5388b242ca7SSai Krishna Potthuri return ret; 5398b242ca7SSai Krishna Potthuri 5408b242ca7SSai Krishna Potthuri *ngroups = payload[1]; 5418b242ca7SSai Krishna Potthuri 542fa99e701SSai Krishna Potthuri return 0; 5438b242ca7SSai Krishna Potthuri } 5448b242ca7SSai Krishna Potthuri 5458b242ca7SSai Krishna Potthuri /** 5468b242ca7SSai Krishna Potthuri * zynqmp_pinctrl_prepare_func_groups() - prepare function and groups data 5478b242ca7SSai Krishna Potthuri * @dev: Device pointer. 5488b242ca7SSai Krishna Potthuri * @fid: Function ID. 5498b242ca7SSai Krishna Potthuri * @func: Function data. 5508b242ca7SSai Krishna Potthuri * @groups: Groups data. 5518b242ca7SSai Krishna Potthuri * 5528b242ca7SSai Krishna Potthuri * Query firmware to get group IDs for each function. Firmware returns 553fa99e701SSai Krishna Potthuri * group IDs. Based on the group index for the function, group names in 5548b242ca7SSai Krishna Potthuri * the function are stored. For example, the first group in "eth0" function 555fa99e701SSai Krishna Potthuri * is named as "eth0_0" and the second group as "eth0_1" and so on. 5568b242ca7SSai Krishna Potthuri * 5578b242ca7SSai Krishna Potthuri * Based on the group ID received from the firmware, function stores name of 5588b242ca7SSai Krishna Potthuri * the group for that group ID. For example, if "eth0" first group ID 5598b242ca7SSai Krishna Potthuri * is x, groups[x] name will be stored as "eth0_0". 5608b242ca7SSai Krishna Potthuri * 5618b242ca7SSai Krishna Potthuri * Once done for each function, each function would have its group names 562fa99e701SSai Krishna Potthuri * and each group would also have their names. 5638b242ca7SSai Krishna Potthuri * 5648b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 5658b242ca7SSai Krishna Potthuri */ 5668b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_prepare_func_groups(struct device *dev, u32 fid, 5678b242ca7SSai Krishna Potthuri struct zynqmp_pmux_function *func, 5688b242ca7SSai Krishna Potthuri struct zynqmp_pctrl_group *groups) 5698b242ca7SSai Krishna Potthuri { 5708b242ca7SSai Krishna Potthuri u16 resp[NUM_GROUPS_PER_RESP] = {0}; 5718b242ca7SSai Krishna Potthuri const char **fgroups; 572*f28cbab9SSean Anderson int ret, index, i, pin; 573*f28cbab9SSean Anderson unsigned int npins; 574*f28cbab9SSean Anderson unsigned long *used_pins __free(bitmap) = 575*f28cbab9SSean Anderson bitmap_zalloc(zynqmp_desc.npins, GFP_KERNEL); 5768b242ca7SSai Krishna Potthuri 577*f28cbab9SSean Anderson if (!used_pins) 5788b242ca7SSai Krishna Potthuri return -ENOMEM; 5798b242ca7SSai Krishna Potthuri 5808b242ca7SSai Krishna Potthuri for (index = 0; index < func->ngroups; index += NUM_GROUPS_PER_RESP) { 5818b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_get_function_groups(fid, index, resp); 5828b242ca7SSai Krishna Potthuri if (ret) 5838b242ca7SSai Krishna Potthuri return ret; 5848b242ca7SSai Krishna Potthuri 5858b242ca7SSai Krishna Potthuri for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { 5868b242ca7SSai Krishna Potthuri if (resp[i] == NA_GROUP) 5878b242ca7SSai Krishna Potthuri goto done; 5888b242ca7SSai Krishna Potthuri 5898b242ca7SSai Krishna Potthuri if (resp[i] == RESERVED_GROUP) 5908b242ca7SSai Krishna Potthuri continue; 5918b242ca7SSai Krishna Potthuri 5928b242ca7SSai Krishna Potthuri groups[resp[i]].name = devm_kasprintf(dev, GFP_KERNEL, 5938b242ca7SSai Krishna Potthuri "%s_%d_grp", 5948b242ca7SSai Krishna Potthuri func->name, 5958b242ca7SSai Krishna Potthuri index + i); 5968b242ca7SSai Krishna Potthuri if (!groups[resp[i]].name) 5978b242ca7SSai Krishna Potthuri return -ENOMEM; 598*f28cbab9SSean Anderson 599*f28cbab9SSean Anderson for (pin = 0; pin < groups[resp[i]].npins; pin++) 600*f28cbab9SSean Anderson __set_bit(groups[resp[i]].pins[pin], used_pins); 6018b242ca7SSai Krishna Potthuri } 6028b242ca7SSai Krishna Potthuri } 6038b242ca7SSai Krishna Potthuri done: 604*f28cbab9SSean Anderson npins = bitmap_weight(used_pins, zynqmp_desc.npins); 605*f28cbab9SSean Anderson fgroups = devm_kcalloc(dev, size_add(func->ngroups, npins), 606*f28cbab9SSean Anderson sizeof(*fgroups), GFP_KERNEL); 607*f28cbab9SSean Anderson if (!fgroups) 608*f28cbab9SSean Anderson return -ENOMEM; 609*f28cbab9SSean Anderson 610*f28cbab9SSean Anderson for (i = 0; i < func->ngroups; i++) { 611*f28cbab9SSean Anderson fgroups[i] = devm_kasprintf(dev, GFP_KERNEL, "%s_%d_grp", 612*f28cbab9SSean Anderson func->name, i); 613*f28cbab9SSean Anderson if (!fgroups[i]) 614*f28cbab9SSean Anderson return -ENOMEM; 615*f28cbab9SSean Anderson } 616*f28cbab9SSean Anderson 617*f28cbab9SSean Anderson pin = 0; 618*f28cbab9SSean Anderson for_each_set_bit(pin, used_pins, zynqmp_desc.npins) 619*f28cbab9SSean Anderson fgroups[i++] = zynqmp_desc.pins[pin].name; 620*f28cbab9SSean Anderson 6218b242ca7SSai Krishna Potthuri func->groups = fgroups; 622*f28cbab9SSean Anderson func->ngroups += npins; 6238b242ca7SSai Krishna Potthuri 624fa99e701SSai Krishna Potthuri return 0; 6258b242ca7SSai Krishna Potthuri } 6268b242ca7SSai Krishna Potthuri 6278b242ca7SSai Krishna Potthuri static void zynqmp_pinctrl_get_function_name(u32 fid, char *name) 6288b242ca7SSai Krishna Potthuri { 6298b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 6308b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 6318b242ca7SSai Krishna Potthuri 6328b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_FUNCTION_NAME; 6338b242ca7SSai Krishna Potthuri qdata.arg1 = fid; 6348b242ca7SSai Krishna Potthuri 6358b242ca7SSai Krishna Potthuri /* 6368b242ca7SSai Krishna Potthuri * Name of the function is maximum 16 bytes and cannot 6378b242ca7SSai Krishna Potthuri * accommodate the return value in SMC buffers, hence ignoring 6388b242ca7SSai Krishna Potthuri * the return value for this specific qid. 6398b242ca7SSai Krishna Potthuri */ 6408b242ca7SSai Krishna Potthuri zynqmp_pm_query_data(qdata, payload); 6418b242ca7SSai Krishna Potthuri memcpy(name, payload, PINCTRL_GET_FUNC_NAME_RESP_LEN); 6428b242ca7SSai Krishna Potthuri } 6438b242ca7SSai Krishna Potthuri 6448b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_get_num_functions(unsigned int *nfuncs) 6458b242ca7SSai Krishna Potthuri { 6468b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 6478b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 6488b242ca7SSai Krishna Potthuri int ret; 6498b242ca7SSai Krishna Potthuri 6508b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_NUM_FUNCTIONS; 6518b242ca7SSai Krishna Potthuri 6528b242ca7SSai Krishna Potthuri ret = zynqmp_pm_query_data(qdata, payload); 6538b242ca7SSai Krishna Potthuri if (ret) 6548b242ca7SSai Krishna Potthuri return ret; 6558b242ca7SSai Krishna Potthuri 6568b242ca7SSai Krishna Potthuri *nfuncs = payload[1]; 6578b242ca7SSai Krishna Potthuri 658fa99e701SSai Krishna Potthuri return 0; 6598b242ca7SSai Krishna Potthuri } 6608b242ca7SSai Krishna Potthuri 6618b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_get_pin_groups(u32 pin, u32 index, u16 *groups) 6628b242ca7SSai Krishna Potthuri { 6638b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 6648b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 6658b242ca7SSai Krishna Potthuri int ret; 6668b242ca7SSai Krishna Potthuri 6678b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_PIN_GROUPS; 6688b242ca7SSai Krishna Potthuri qdata.arg1 = pin; 6698b242ca7SSai Krishna Potthuri qdata.arg2 = index; 6708b242ca7SSai Krishna Potthuri 6718b242ca7SSai Krishna Potthuri ret = zynqmp_pm_query_data(qdata, payload); 6728b242ca7SSai Krishna Potthuri if (ret) 6738b242ca7SSai Krishna Potthuri return ret; 6748b242ca7SSai Krishna Potthuri 6758b242ca7SSai Krishna Potthuri memcpy(groups, &payload[1], PINCTRL_GET_PIN_GROUPS_RESP_LEN); 6768b242ca7SSai Krishna Potthuri 677fa99e701SSai Krishna Potthuri return 0; 6788b242ca7SSai Krishna Potthuri } 6798b242ca7SSai Krishna Potthuri 6808b242ca7SSai Krishna Potthuri static void zynqmp_pinctrl_group_add_pin(struct zynqmp_pctrl_group *group, 6818b242ca7SSai Krishna Potthuri unsigned int pin) 6828b242ca7SSai Krishna Potthuri { 6838b242ca7SSai Krishna Potthuri group->pins[group->npins++] = pin; 6848b242ca7SSai Krishna Potthuri } 6858b242ca7SSai Krishna Potthuri 6868b242ca7SSai Krishna Potthuri /** 6878b242ca7SSai Krishna Potthuri * zynqmp_pinctrl_create_pin_groups() - assign pins to respective groups 6888b242ca7SSai Krishna Potthuri * @dev: Device pointer. 6898b242ca7SSai Krishna Potthuri * @groups: Groups data. 6908b242ca7SSai Krishna Potthuri * @pin: Pin number. 6918b242ca7SSai Krishna Potthuri * 6928b242ca7SSai Krishna Potthuri * Query firmware to get groups available for the given pin. 6938b242ca7SSai Krishna Potthuri * Based on the firmware response(group IDs for the pin), add 6948b242ca7SSai Krishna Potthuri * pin number to the respective group's pin array. 6958b242ca7SSai Krishna Potthuri * 696fa99e701SSai Krishna Potthuri * Once all pins are queries, each group would have its number 6978b242ca7SSai Krishna Potthuri * of pins and pin numbers data. 6988b242ca7SSai Krishna Potthuri * 6998b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 7008b242ca7SSai Krishna Potthuri */ 7018b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_create_pin_groups(struct device *dev, 7028b242ca7SSai Krishna Potthuri struct zynqmp_pctrl_group *groups, 7038b242ca7SSai Krishna Potthuri unsigned int pin) 7048b242ca7SSai Krishna Potthuri { 7058b242ca7SSai Krishna Potthuri u16 resp[NUM_GROUPS_PER_RESP] = {0}; 7068b242ca7SSai Krishna Potthuri int ret, i, index = 0; 7078b242ca7SSai Krishna Potthuri 7088b242ca7SSai Krishna Potthuri do { 7098b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_get_pin_groups(pin, index, resp); 7108b242ca7SSai Krishna Potthuri if (ret) 7118b242ca7SSai Krishna Potthuri return ret; 7128b242ca7SSai Krishna Potthuri 7138b242ca7SSai Krishna Potthuri for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { 7148b242ca7SSai Krishna Potthuri if (resp[i] == NA_GROUP) 7158b242ca7SSai Krishna Potthuri return ret; 7168b242ca7SSai Krishna Potthuri 7178b242ca7SSai Krishna Potthuri if (resp[i] == RESERVED_GROUP) 7188b242ca7SSai Krishna Potthuri continue; 7198b242ca7SSai Krishna Potthuri 7208b242ca7SSai Krishna Potthuri zynqmp_pinctrl_group_add_pin(&groups[resp[i]], pin); 7218b242ca7SSai Krishna Potthuri } 7228b242ca7SSai Krishna Potthuri index += NUM_GROUPS_PER_RESP; 7238b242ca7SSai Krishna Potthuri } while (index <= MAX_PIN_GROUPS); 7248b242ca7SSai Krishna Potthuri 725fa99e701SSai Krishna Potthuri return 0; 7268b242ca7SSai Krishna Potthuri } 7278b242ca7SSai Krishna Potthuri 7288b242ca7SSai Krishna Potthuri /** 7298b242ca7SSai Krishna Potthuri * zynqmp_pinctrl_prepare_group_pins() - prepare each group's pin data 7308b242ca7SSai Krishna Potthuri * @dev: Device pointer. 7318b242ca7SSai Krishna Potthuri * @groups: Groups data. 7328b242ca7SSai Krishna Potthuri * @ngroups: Number of groups. 7338b242ca7SSai Krishna Potthuri * 7348b242ca7SSai Krishna Potthuri * Prepare pin number and number of pins data for each pins. 7358b242ca7SSai Krishna Potthuri * 7368b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 7378b242ca7SSai Krishna Potthuri */ 7388b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_prepare_group_pins(struct device *dev, 7398b242ca7SSai Krishna Potthuri struct zynqmp_pctrl_group *groups, 7408b242ca7SSai Krishna Potthuri unsigned int ngroups) 7418b242ca7SSai Krishna Potthuri { 7428b242ca7SSai Krishna Potthuri unsigned int pin; 7438b242ca7SSai Krishna Potthuri int ret; 7448b242ca7SSai Krishna Potthuri 7458b242ca7SSai Krishna Potthuri for (pin = 0; pin < zynqmp_desc.npins; pin++) { 74650287367SSwati Agarwal ret = zynqmp_pinctrl_create_pin_groups(dev, groups, zynqmp_desc.pins[pin].number); 7478b242ca7SSai Krishna Potthuri if (ret) 7488b242ca7SSai Krishna Potthuri return ret; 7498b242ca7SSai Krishna Potthuri } 7508b242ca7SSai Krishna Potthuri 7518b242ca7SSai Krishna Potthuri return 0; 7528b242ca7SSai Krishna Potthuri } 7538b242ca7SSai Krishna Potthuri 7548b242ca7SSai Krishna Potthuri /** 7558b242ca7SSai Krishna Potthuri * zynqmp_pinctrl_prepare_function_info() - prepare function info 7568b242ca7SSai Krishna Potthuri * @dev: Device pointer. 7578b242ca7SSai Krishna Potthuri * @pctrl: Pin control driver data. 7588b242ca7SSai Krishna Potthuri * 7598b242ca7SSai Krishna Potthuri * Query firmware for functions, groups and pin information and 7608b242ca7SSai Krishna Potthuri * prepare pin control driver data. 7618b242ca7SSai Krishna Potthuri * 7628b242ca7SSai Krishna Potthuri * Query number of functions and number of function groups (number 763fa99e701SSai Krishna Potthuri * of groups in the given function) to allocate required memory buffers 7648b242ca7SSai Krishna Potthuri * for functions and groups. Once buffers are allocated to store 7658b242ca7SSai Krishna Potthuri * functions and groups data, query and store required information 7668b242ca7SSai Krishna Potthuri * (number of groups and group names for each function, number of 7678b242ca7SSai Krishna Potthuri * pins and pin numbers for each group). 7688b242ca7SSai Krishna Potthuri * 7698b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 7708b242ca7SSai Krishna Potthuri */ 7718b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_prepare_function_info(struct device *dev, 7728b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl) 7738b242ca7SSai Krishna Potthuri { 7748b242ca7SSai Krishna Potthuri struct zynqmp_pmux_function *funcs; 7758b242ca7SSai Krishna Potthuri struct zynqmp_pctrl_group *groups; 7768b242ca7SSai Krishna Potthuri int ret, i; 7778b242ca7SSai Krishna Potthuri 7788b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_get_num_functions(&pctrl->nfuncs); 7798b242ca7SSai Krishna Potthuri if (ret) 7808b242ca7SSai Krishna Potthuri return ret; 7818b242ca7SSai Krishna Potthuri 782f6f62a9aSErick Archer funcs = devm_kcalloc(dev, pctrl->nfuncs, sizeof(*funcs), GFP_KERNEL); 7838b242ca7SSai Krishna Potthuri if (!funcs) 7848b242ca7SSai Krishna Potthuri return -ENOMEM; 7858b242ca7SSai Krishna Potthuri 7868b242ca7SSai Krishna Potthuri for (i = 0; i < pctrl->nfuncs; i++) { 7878b242ca7SSai Krishna Potthuri zynqmp_pinctrl_get_function_name(i, funcs[i].name); 7888b242ca7SSai Krishna Potthuri 7898b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_get_func_num_groups(i, &funcs[i].ngroups); 7908b242ca7SSai Krishna Potthuri if (ret) 7918b242ca7SSai Krishna Potthuri return ret; 7928b242ca7SSai Krishna Potthuri 7938b242ca7SSai Krishna Potthuri pctrl->ngroups += funcs[i].ngroups; 7948b242ca7SSai Krishna Potthuri } 7958b242ca7SSai Krishna Potthuri 796f6f62a9aSErick Archer groups = devm_kcalloc(dev, pctrl->ngroups, sizeof(*groups), GFP_KERNEL); 7978b242ca7SSai Krishna Potthuri if (!groups) 7988b242ca7SSai Krishna Potthuri return -ENOMEM; 7998b242ca7SSai Krishna Potthuri 800*f28cbab9SSean Anderson ret = zynqmp_pinctrl_prepare_group_pins(dev, groups, pctrl->ngroups); 801*f28cbab9SSean Anderson if (ret) 802*f28cbab9SSean Anderson return ret; 803*f28cbab9SSean Anderson 8048b242ca7SSai Krishna Potthuri for (i = 0; i < pctrl->nfuncs; i++) { 8058b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_prepare_func_groups(dev, i, &funcs[i], 8068b242ca7SSai Krishna Potthuri groups); 8078b242ca7SSai Krishna Potthuri if (ret) 8088b242ca7SSai Krishna Potthuri return ret; 8098b242ca7SSai Krishna Potthuri } 8108b242ca7SSai Krishna Potthuri 8118b242ca7SSai Krishna Potthuri pctrl->funcs = funcs; 8128b242ca7SSai Krishna Potthuri pctrl->groups = groups; 8138b242ca7SSai Krishna Potthuri 814fa99e701SSai Krishna Potthuri return 0; 8158b242ca7SSai Krishna Potthuri } 8168b242ca7SSai Krishna Potthuri 8178b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_get_num_pins(unsigned int *npins) 8188b242ca7SSai Krishna Potthuri { 8198b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 8208b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 8218b242ca7SSai Krishna Potthuri int ret; 8228b242ca7SSai Krishna Potthuri 8238b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_NUM_PINS; 8248b242ca7SSai Krishna Potthuri 8258b242ca7SSai Krishna Potthuri ret = zynqmp_pm_query_data(qdata, payload); 8268b242ca7SSai Krishna Potthuri if (ret) 8278b242ca7SSai Krishna Potthuri return ret; 8288b242ca7SSai Krishna Potthuri 8298b242ca7SSai Krishna Potthuri *npins = payload[1]; 8308b242ca7SSai Krishna Potthuri 831fa99e701SSai Krishna Potthuri return 0; 8328b242ca7SSai Krishna Potthuri } 8338b242ca7SSai Krishna Potthuri 8348b242ca7SSai Krishna Potthuri /** 8358b242ca7SSai Krishna Potthuri * zynqmp_pinctrl_prepare_pin_desc() - prepare pin description info 8368b242ca7SSai Krishna Potthuri * @dev: Device pointer. 8378b242ca7SSai Krishna Potthuri * @zynqmp_pins: Pin information. 8388b242ca7SSai Krishna Potthuri * @npins: Number of pins. 8398b242ca7SSai Krishna Potthuri * 8408b242ca7SSai Krishna Potthuri * Query number of pins information from firmware and prepare pin 8418b242ca7SSai Krishna Potthuri * description containing pin number and pin name. 8428b242ca7SSai Krishna Potthuri * 8438b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 8448b242ca7SSai Krishna Potthuri */ 8458b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev, 8468b242ca7SSai Krishna Potthuri const struct pinctrl_pin_desc 8478b242ca7SSai Krishna Potthuri **zynqmp_pins, 8488b242ca7SSai Krishna Potthuri unsigned int *npins) 8498b242ca7SSai Krishna Potthuri { 8508b242ca7SSai Krishna Potthuri struct pinctrl_pin_desc *pins, *pin; 8518b242ca7SSai Krishna Potthuri int ret; 8528b242ca7SSai Krishna Potthuri int i; 8538b242ca7SSai Krishna Potthuri 8548b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_get_num_pins(npins); 8558b242ca7SSai Krishna Potthuri if (ret) 8568b242ca7SSai Krishna Potthuri return ret; 8578b242ca7SSai Krishna Potthuri 858f6f62a9aSErick Archer pins = devm_kcalloc(dev, *npins, sizeof(*pins), GFP_KERNEL); 8598b242ca7SSai Krishna Potthuri if (!pins) 8608b242ca7SSai Krishna Potthuri return -ENOMEM; 8618b242ca7SSai Krishna Potthuri 8628b242ca7SSai Krishna Potthuri for (i = 0; i < *npins; i++) { 8638b242ca7SSai Krishna Potthuri pin = &pins[i]; 8648b242ca7SSai Krishna Potthuri pin->number = i; 865500c77eeSGerhard Engleder pin->name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", 866500c77eeSGerhard Engleder ZYNQMP_PIN_PREFIX, i); 867500c77eeSGerhard Engleder if (!pin->name) 868500c77eeSGerhard Engleder return -ENOMEM; 8698b242ca7SSai Krishna Potthuri } 8708b242ca7SSai Krishna Potthuri 8718b242ca7SSai Krishna Potthuri *zynqmp_pins = pins; 8728b242ca7SSai Krishna Potthuri 8738b242ca7SSai Krishna Potthuri return 0; 8748b242ca7SSai Krishna Potthuri } 8758b242ca7SSai Krishna Potthuri 8768b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_probe(struct platform_device *pdev) 8778b242ca7SSai Krishna Potthuri { 8788b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl; 8798b242ca7SSai Krishna Potthuri int ret; 8808b242ca7SSai Krishna Potthuri 8818b242ca7SSai Krishna Potthuri pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); 8828b242ca7SSai Krishna Potthuri if (!pctrl) 8838b242ca7SSai Krishna Potthuri return -ENOMEM; 8848b242ca7SSai Krishna Potthuri 8858b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_prepare_pin_desc(&pdev->dev, 8868b242ca7SSai Krishna Potthuri &zynqmp_desc.pins, 8878b242ca7SSai Krishna Potthuri &zynqmp_desc.npins); 8888b242ca7SSai Krishna Potthuri if (ret) { 889fa99e701SSai Krishna Potthuri dev_err(&pdev->dev, "pin desc prepare fail with %d\n", ret); 8908b242ca7SSai Krishna Potthuri return ret; 8918b242ca7SSai Krishna Potthuri } 8928b242ca7SSai Krishna Potthuri 8938b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_prepare_function_info(&pdev->dev, pctrl); 8948b242ca7SSai Krishna Potthuri if (ret) { 895fa99e701SSai Krishna Potthuri dev_err(&pdev->dev, "function info prepare fail with %d\n", ret); 8968b242ca7SSai Krishna Potthuri return ret; 8978b242ca7SSai Krishna Potthuri } 8988b242ca7SSai Krishna Potthuri 899fa99e701SSai Krishna Potthuri pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &zynqmp_desc, pctrl); 9008b242ca7SSai Krishna Potthuri if (IS_ERR(pctrl->pctrl)) 9018b242ca7SSai Krishna Potthuri return PTR_ERR(pctrl->pctrl); 9028b242ca7SSai Krishna Potthuri 9038b242ca7SSai Krishna Potthuri platform_set_drvdata(pdev, pctrl); 9048b242ca7SSai Krishna Potthuri 9058b242ca7SSai Krishna Potthuri return ret; 9068b242ca7SSai Krishna Potthuri } 9078b242ca7SSai Krishna Potthuri 9088b242ca7SSai Krishna Potthuri static const struct of_device_id zynqmp_pinctrl_of_match[] = { 9098b242ca7SSai Krishna Potthuri { .compatible = "xlnx,zynqmp-pinctrl" }, 9108b242ca7SSai Krishna Potthuri { } 9118b242ca7SSai Krishna Potthuri }; 9128b242ca7SSai Krishna Potthuri MODULE_DEVICE_TABLE(of, zynqmp_pinctrl_of_match); 9138b242ca7SSai Krishna Potthuri 9148b242ca7SSai Krishna Potthuri static struct platform_driver zynqmp_pinctrl_driver = { 9158b242ca7SSai Krishna Potthuri .driver = { 9168b242ca7SSai Krishna Potthuri .name = "zynqmp-pinctrl", 9178b242ca7SSai Krishna Potthuri .of_match_table = zynqmp_pinctrl_of_match, 9188b242ca7SSai Krishna Potthuri }, 9198b242ca7SSai Krishna Potthuri .probe = zynqmp_pinctrl_probe, 9208b242ca7SSai Krishna Potthuri }; 9218b242ca7SSai Krishna Potthuri module_platform_driver(zynqmp_pinctrl_driver); 9228b242ca7SSai Krishna Potthuri 9238b242ca7SSai Krishna Potthuri MODULE_AUTHOR("Sai Krishna Potthuri <lakshmi.sai.krishna.potthuri@xilinx.com>"); 9248b242ca7SSai Krishna Potthuri MODULE_DESCRIPTION("ZynqMP Pin Controller Driver"); 9258b242ca7SSai Krishna Potthuri MODULE_LICENSE("GPL v2"); 926