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 138b242ca7SSai Krishna Potthuri #include <linux/init.h> 148b242ca7SSai Krishna Potthuri #include <linux/module.h> 158b242ca7SSai Krishna Potthuri #include <linux/of_address.h> 168b242ca7SSai Krishna Potthuri #include <linux/platform_device.h> 17e9d10adcSAndy Shevchenko 188b242ca7SSai Krishna Potthuri #include <linux/firmware/xlnx-zynqmp.h> 198b242ca7SSai Krishna Potthuri 208b242ca7SSai Krishna Potthuri #include <linux/pinctrl/pinconf-generic.h> 21e9d10adcSAndy Shevchenko #include <linux/pinctrl/pinconf.h> 22e9d10adcSAndy Shevchenko #include <linux/pinctrl/pinctrl.h> 23e9d10adcSAndy Shevchenko #include <linux/pinctrl/pinmux.h> 248b242ca7SSai Krishna Potthuri 258b242ca7SSai Krishna Potthuri #include "core.h" 268b242ca7SSai Krishna Potthuri #include "pinctrl-utils.h" 278b242ca7SSai Krishna Potthuri 288b242ca7SSai Krishna Potthuri #define ZYNQMP_PIN_PREFIX "MIO" 298b242ca7SSai Krishna Potthuri #define PINCTRL_GET_FUNC_NAME_RESP_LEN 16 308b242ca7SSai Krishna Potthuri #define MAX_FUNC_NAME_LEN 16 318b242ca7SSai Krishna Potthuri #define MAX_GROUP_PIN 50 328b242ca7SSai Krishna Potthuri #define MAX_PIN_GROUPS 50 338b242ca7SSai Krishna Potthuri #define END_OF_FUNCTIONS "END_OF_FUNCTIONS" 348b242ca7SSai Krishna Potthuri #define NUM_GROUPS_PER_RESP 6 358b242ca7SSai Krishna Potthuri 368b242ca7SSai Krishna Potthuri #define PINCTRL_GET_FUNC_GROUPS_RESP_LEN 12 378b242ca7SSai Krishna Potthuri #define PINCTRL_GET_PIN_GROUPS_RESP_LEN 12 388b242ca7SSai Krishna Potthuri #define NA_GROUP 0xFFFF 398b242ca7SSai Krishna Potthuri #define RESERVED_GROUP 0xFFFE 408b242ca7SSai Krishna Potthuri 418b242ca7SSai Krishna Potthuri #define DRIVE_STRENGTH_2MA 2 428b242ca7SSai Krishna Potthuri #define DRIVE_STRENGTH_4MA 4 438b242ca7SSai Krishna Potthuri #define DRIVE_STRENGTH_8MA 8 448b242ca7SSai Krishna Potthuri #define DRIVE_STRENGTH_12MA 12 458b242ca7SSai Krishna Potthuri 468b242ca7SSai Krishna Potthuri /** 478b242ca7SSai Krishna Potthuri * struct zynqmp_pmux_function - a pinmux function 488b242ca7SSai Krishna Potthuri * @name: Name of the pin mux function 498b242ca7SSai Krishna Potthuri * @groups: List of pin groups for this function 508b242ca7SSai Krishna Potthuri * @ngroups: Number of entries in @groups 518b242ca7SSai Krishna Potthuri * @node: Firmware node matching with the function 528b242ca7SSai Krishna Potthuri * 538b242ca7SSai Krishna Potthuri * This structure holds information about pin control function 548b242ca7SSai Krishna Potthuri * and function group names supporting that function. 558b242ca7SSai Krishna Potthuri */ 568b242ca7SSai Krishna Potthuri struct zynqmp_pmux_function { 578b242ca7SSai Krishna Potthuri char name[MAX_FUNC_NAME_LEN]; 588b242ca7SSai Krishna Potthuri const char * const *groups; 598b242ca7SSai Krishna Potthuri unsigned int ngroups; 608b242ca7SSai Krishna Potthuri }; 618b242ca7SSai Krishna Potthuri 628b242ca7SSai Krishna Potthuri /** 638b242ca7SSai Krishna Potthuri * struct zynqmp_pinctrl - driver data 648b242ca7SSai Krishna Potthuri * @pctrl: Pin control device 658b242ca7SSai Krishna Potthuri * @groups: Pin groups 668b242ca7SSai Krishna Potthuri * @ngroups: Number of @groups 678b242ca7SSai Krishna Potthuri * @funcs: Pin mux functions 688b242ca7SSai Krishna Potthuri * @nfuncs: Number of @funcs 698b242ca7SSai Krishna Potthuri * 708b242ca7SSai Krishna Potthuri * This struct is stored as driver data and used to retrieve 718b242ca7SSai Krishna Potthuri * information regarding pin control functions, groups and 728b242ca7SSai Krishna Potthuri * group pins. 738b242ca7SSai Krishna Potthuri */ 748b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl { 758b242ca7SSai Krishna Potthuri struct pinctrl_dev *pctrl; 768b242ca7SSai Krishna Potthuri const struct zynqmp_pctrl_group *groups; 778b242ca7SSai Krishna Potthuri unsigned int ngroups; 788b242ca7SSai Krishna Potthuri const struct zynqmp_pmux_function *funcs; 798b242ca7SSai Krishna Potthuri unsigned int nfuncs; 808b242ca7SSai Krishna Potthuri }; 818b242ca7SSai Krishna Potthuri 828b242ca7SSai Krishna Potthuri /** 838b242ca7SSai Krishna Potthuri * struct zynqmp_pctrl_group - Pin control group info 848b242ca7SSai Krishna Potthuri * @name: Group name 858b242ca7SSai Krishna Potthuri * @pins: Group pin numbers 868b242ca7SSai Krishna Potthuri * @npins: Number of pins in the group 878b242ca7SSai Krishna Potthuri */ 888b242ca7SSai Krishna Potthuri struct zynqmp_pctrl_group { 898b242ca7SSai Krishna Potthuri const char *name; 908b242ca7SSai Krishna Potthuri unsigned int pins[MAX_GROUP_PIN]; 918b242ca7SSai Krishna Potthuri unsigned int npins; 928b242ca7SSai Krishna Potthuri }; 938b242ca7SSai Krishna Potthuri 948b242ca7SSai Krishna Potthuri static struct pinctrl_desc zynqmp_desc; 958b242ca7SSai Krishna Potthuri 968b242ca7SSai Krishna Potthuri static int zynqmp_pctrl_get_groups_count(struct pinctrl_dev *pctldev) 978b242ca7SSai Krishna Potthuri { 988b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 998b242ca7SSai Krishna Potthuri 1008b242ca7SSai Krishna Potthuri return pctrl->ngroups; 1018b242ca7SSai Krishna Potthuri } 1028b242ca7SSai Krishna Potthuri 1038b242ca7SSai Krishna Potthuri static const char *zynqmp_pctrl_get_group_name(struct pinctrl_dev *pctldev, 1048b242ca7SSai Krishna Potthuri unsigned int selector) 1058b242ca7SSai Krishna Potthuri { 1068b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 1078b242ca7SSai Krishna Potthuri 1088b242ca7SSai Krishna Potthuri return pctrl->groups[selector].name; 1098b242ca7SSai Krishna Potthuri } 1108b242ca7SSai Krishna Potthuri 1118b242ca7SSai Krishna Potthuri static int zynqmp_pctrl_get_group_pins(struct pinctrl_dev *pctldev, 1128b242ca7SSai Krishna Potthuri unsigned int selector, 1138b242ca7SSai Krishna Potthuri const unsigned int **pins, 1148b242ca7SSai Krishna Potthuri unsigned int *npins) 1158b242ca7SSai Krishna Potthuri { 1168b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 1178b242ca7SSai Krishna Potthuri 1188b242ca7SSai Krishna Potthuri *pins = pctrl->groups[selector].pins; 1198b242ca7SSai Krishna Potthuri *npins = pctrl->groups[selector].npins; 1208b242ca7SSai Krishna Potthuri 1218b242ca7SSai Krishna Potthuri return 0; 1228b242ca7SSai Krishna Potthuri } 1238b242ca7SSai Krishna Potthuri 1248b242ca7SSai Krishna Potthuri static const struct pinctrl_ops zynqmp_pctrl_ops = { 1258b242ca7SSai Krishna Potthuri .get_groups_count = zynqmp_pctrl_get_groups_count, 1268b242ca7SSai Krishna Potthuri .get_group_name = zynqmp_pctrl_get_group_name, 1278b242ca7SSai Krishna Potthuri .get_group_pins = zynqmp_pctrl_get_group_pins, 1288b242ca7SSai Krishna Potthuri .dt_node_to_map = pinconf_generic_dt_node_to_map_all, 1298b242ca7SSai Krishna Potthuri .dt_free_map = pinctrl_utils_free_map, 1308b242ca7SSai Krishna Potthuri }; 1318b242ca7SSai Krishna Potthuri 1328b242ca7SSai Krishna Potthuri static int zynqmp_pinmux_request_pin(struct pinctrl_dev *pctldev, 1338b242ca7SSai Krishna Potthuri unsigned int pin) 1348b242ca7SSai Krishna Potthuri { 1358b242ca7SSai Krishna Potthuri int ret; 1368b242ca7SSai Krishna Potthuri 1378b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_request(pin); 1388b242ca7SSai Krishna Potthuri if (ret) { 1398b242ca7SSai Krishna Potthuri dev_err(pctldev->dev, "request failed for pin %u\n", pin); 1408b242ca7SSai Krishna Potthuri return ret; 1418b242ca7SSai Krishna Potthuri } 1428b242ca7SSai Krishna Potthuri 1438b242ca7SSai Krishna Potthuri return 0; 1448b242ca7SSai Krishna Potthuri } 1458b242ca7SSai Krishna Potthuri 1468b242ca7SSai Krishna Potthuri static int zynqmp_pmux_get_functions_count(struct pinctrl_dev *pctldev) 1478b242ca7SSai Krishna Potthuri { 1488b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 1498b242ca7SSai Krishna Potthuri 1508b242ca7SSai Krishna Potthuri return pctrl->nfuncs; 1518b242ca7SSai Krishna Potthuri } 1528b242ca7SSai Krishna Potthuri 1538b242ca7SSai Krishna Potthuri static const char *zynqmp_pmux_get_function_name(struct pinctrl_dev *pctldev, 1548b242ca7SSai Krishna Potthuri unsigned int selector) 1558b242ca7SSai Krishna Potthuri { 1568b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 1578b242ca7SSai Krishna Potthuri 1588b242ca7SSai Krishna Potthuri return pctrl->funcs[selector].name; 1598b242ca7SSai Krishna Potthuri } 1608b242ca7SSai Krishna Potthuri 1618b242ca7SSai Krishna Potthuri /** 1628b242ca7SSai Krishna Potthuri * zynqmp_pmux_get_function_groups() - Get groups for the function 1638b242ca7SSai Krishna Potthuri * @pctldev: Pincontrol device pointer. 1648b242ca7SSai Krishna Potthuri * @selector: Function ID 1658b242ca7SSai Krishna Potthuri * @groups: Group names. 1668b242ca7SSai Krishna Potthuri * @num_groups: Number of function groups. 1678b242ca7SSai Krishna Potthuri * 1688b242ca7SSai Krishna Potthuri * Get function's group count and group names. 169eb1c38c6SSai Krishna Potthuri * 170eb1c38c6SSai Krishna Potthuri * Return: 0 1718b242ca7SSai Krishna Potthuri */ 1728b242ca7SSai Krishna Potthuri static int zynqmp_pmux_get_function_groups(struct pinctrl_dev *pctldev, 1738b242ca7SSai Krishna Potthuri unsigned int selector, 1748b242ca7SSai Krishna Potthuri const char * const **groups, 1758b242ca7SSai Krishna Potthuri unsigned * const num_groups) 1768b242ca7SSai Krishna Potthuri { 1778b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 1788b242ca7SSai Krishna Potthuri 1798b242ca7SSai Krishna Potthuri *groups = pctrl->funcs[selector].groups; 1808b242ca7SSai Krishna Potthuri *num_groups = pctrl->funcs[selector].ngroups; 1818b242ca7SSai Krishna Potthuri 1828b242ca7SSai Krishna Potthuri return 0; 1838b242ca7SSai Krishna Potthuri } 1848b242ca7SSai Krishna Potthuri 1858b242ca7SSai Krishna Potthuri /** 1868b242ca7SSai Krishna Potthuri * zynqmp_pinmux_set_mux() - Set requested function for the group 1878b242ca7SSai Krishna Potthuri * @pctldev: Pincontrol device pointer. 1888b242ca7SSai Krishna Potthuri * @function: Function ID. 1898b242ca7SSai Krishna Potthuri * @group: Group ID. 1908b242ca7SSai Krishna Potthuri * 1918b242ca7SSai Krishna Potthuri * Loop through all pins of the group and call firmware API 1928b242ca7SSai Krishna Potthuri * to set requested function for all pins in the group. 1938b242ca7SSai Krishna Potthuri * 1948b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 1958b242ca7SSai Krishna Potthuri */ 1968b242ca7SSai Krishna Potthuri static int zynqmp_pinmux_set_mux(struct pinctrl_dev *pctldev, 1978b242ca7SSai Krishna Potthuri unsigned int function, 1988b242ca7SSai Krishna Potthuri unsigned int group) 1998b242ca7SSai Krishna Potthuri { 2008b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 2018b242ca7SSai Krishna Potthuri const struct zynqmp_pctrl_group *pgrp = &pctrl->groups[group]; 2028b242ca7SSai Krishna Potthuri int ret, i; 2038b242ca7SSai Krishna Potthuri 2048b242ca7SSai Krishna Potthuri for (i = 0; i < pgrp->npins; i++) { 2058b242ca7SSai Krishna Potthuri unsigned int pin = pgrp->pins[i]; 2068b242ca7SSai Krishna Potthuri 2078b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_function(pin, function); 2088b242ca7SSai Krishna Potthuri if (ret) { 2098b242ca7SSai Krishna Potthuri dev_err(pctldev->dev, "set mux failed for pin %u\n", 2108b242ca7SSai Krishna Potthuri pin); 2118b242ca7SSai Krishna Potthuri return ret; 2128b242ca7SSai Krishna Potthuri } 2138b242ca7SSai Krishna Potthuri } 2148b242ca7SSai Krishna Potthuri 2158b242ca7SSai Krishna Potthuri return 0; 2168b242ca7SSai Krishna Potthuri } 2178b242ca7SSai Krishna Potthuri 2188b242ca7SSai Krishna Potthuri static int zynqmp_pinmux_release_pin(struct pinctrl_dev *pctldev, 2198b242ca7SSai Krishna Potthuri unsigned int pin) 2208b242ca7SSai Krishna Potthuri { 2218b242ca7SSai Krishna Potthuri int ret; 2228b242ca7SSai Krishna Potthuri 2238b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_release(pin); 2248b242ca7SSai Krishna Potthuri if (ret) { 2258b242ca7SSai Krishna Potthuri dev_err(pctldev->dev, "free pin failed for pin %u\n", 2268b242ca7SSai Krishna Potthuri pin); 2278b242ca7SSai Krishna Potthuri return ret; 2288b242ca7SSai Krishna Potthuri } 2298b242ca7SSai Krishna Potthuri 2308b242ca7SSai Krishna Potthuri return 0; 2318b242ca7SSai Krishna Potthuri } 2328b242ca7SSai Krishna Potthuri 2338b242ca7SSai Krishna Potthuri static const struct pinmux_ops zynqmp_pinmux_ops = { 2348b242ca7SSai Krishna Potthuri .request = zynqmp_pinmux_request_pin, 2358b242ca7SSai Krishna Potthuri .get_functions_count = zynqmp_pmux_get_functions_count, 2368b242ca7SSai Krishna Potthuri .get_function_name = zynqmp_pmux_get_function_name, 2378b242ca7SSai Krishna Potthuri .get_function_groups = zynqmp_pmux_get_function_groups, 2388b242ca7SSai Krishna Potthuri .set_mux = zynqmp_pinmux_set_mux, 2398b242ca7SSai Krishna Potthuri .free = zynqmp_pinmux_release_pin, 2408b242ca7SSai Krishna Potthuri }; 2418b242ca7SSai Krishna Potthuri 2428b242ca7SSai Krishna Potthuri /** 2438b242ca7SSai Krishna Potthuri * zynqmp_pinconf_cfg_get() - get config value for the pin 2448b242ca7SSai Krishna Potthuri * @pctldev: Pin control device pointer. 2458b242ca7SSai Krishna Potthuri * @pin: Pin number. 2468b242ca7SSai Krishna Potthuri * @config: Value of config param. 2478b242ca7SSai Krishna Potthuri * 2488b242ca7SSai Krishna Potthuri * Get value of the requested configuration parameter for the 2498b242ca7SSai Krishna Potthuri * given pin. 2508b242ca7SSai Krishna Potthuri * 2518b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 2528b242ca7SSai Krishna Potthuri */ 2538b242ca7SSai Krishna Potthuri static int zynqmp_pinconf_cfg_get(struct pinctrl_dev *pctldev, 2548b242ca7SSai Krishna Potthuri unsigned int pin, 2558b242ca7SSai Krishna Potthuri unsigned long *config) 2568b242ca7SSai Krishna Potthuri { 2578b242ca7SSai Krishna Potthuri unsigned int arg, param = pinconf_to_config_param(*config); 2588b242ca7SSai Krishna Potthuri int ret; 2598b242ca7SSai Krishna Potthuri 2608b242ca7SSai Krishna Potthuri switch (param) { 2618b242ca7SSai Krishna Potthuri case PIN_CONFIG_SLEW_RATE: 2628b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_SLEW_RATE; 2638b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 2648b242ca7SSai Krishna Potthuri break; 2658b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_PULL_UP: 2668b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_PULL_CTRL; 2678b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 2688b242ca7SSai Krishna Potthuri if (arg != PM_PINCTRL_BIAS_PULL_UP) 2698b242ca7SSai Krishna Potthuri return -EINVAL; 2708b242ca7SSai Krishna Potthuri 2718b242ca7SSai Krishna Potthuri arg = 1; 2728b242ca7SSai Krishna Potthuri break; 2738b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_PULL_DOWN: 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_DOWN) 2778b242ca7SSai Krishna Potthuri return -EINVAL; 2788b242ca7SSai Krishna Potthuri 2798b242ca7SSai Krishna Potthuri arg = 1; 2808b242ca7SSai Krishna Potthuri break; 2818b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_DISABLE: 2828b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_BIAS_STATUS; 2838b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 2848b242ca7SSai Krishna Potthuri if (arg != PM_PINCTRL_BIAS_DISABLE) 2858b242ca7SSai Krishna Potthuri return -EINVAL; 2868b242ca7SSai Krishna Potthuri 2878b242ca7SSai Krishna Potthuri arg = 1; 2888b242ca7SSai Krishna Potthuri break; 2898b242ca7SSai Krishna Potthuri case PIN_CONFIG_POWER_SOURCE: 2908b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; 2918b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 2928b242ca7SSai Krishna Potthuri break; 2938b242ca7SSai Krishna Potthuri case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 2948b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_SCHMITT_CMOS; 2958b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 2968b242ca7SSai Krishna Potthuri break; 2978b242ca7SSai Krishna Potthuri case PIN_CONFIG_DRIVE_STRENGTH: 2988b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH; 2998b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); 3008b242ca7SSai Krishna Potthuri switch (arg) { 3018b242ca7SSai Krishna Potthuri case PM_PINCTRL_DRIVE_STRENGTH_2MA: 3028b242ca7SSai Krishna Potthuri arg = DRIVE_STRENGTH_2MA; 3038b242ca7SSai Krishna Potthuri break; 3048b242ca7SSai Krishna Potthuri case PM_PINCTRL_DRIVE_STRENGTH_4MA: 3058b242ca7SSai Krishna Potthuri arg = DRIVE_STRENGTH_4MA; 3068b242ca7SSai Krishna Potthuri break; 3078b242ca7SSai Krishna Potthuri case PM_PINCTRL_DRIVE_STRENGTH_8MA: 3088b242ca7SSai Krishna Potthuri arg = DRIVE_STRENGTH_8MA; 3098b242ca7SSai Krishna Potthuri break; 3108b242ca7SSai Krishna Potthuri case PM_PINCTRL_DRIVE_STRENGTH_12MA: 3118b242ca7SSai Krishna Potthuri arg = DRIVE_STRENGTH_12MA; 3128b242ca7SSai Krishna Potthuri break; 3138b242ca7SSai Krishna Potthuri default: 3148b242ca7SSai Krishna Potthuri /* Invalid drive strength */ 3158b242ca7SSai Krishna Potthuri dev_warn(pctldev->dev, 3168b242ca7SSai Krishna Potthuri "Invalid drive strength for pin %d\n", 3178b242ca7SSai Krishna Potthuri pin); 3188b242ca7SSai Krishna Potthuri return -EINVAL; 3198b242ca7SSai Krishna Potthuri } 3208b242ca7SSai Krishna Potthuri break; 3218b242ca7SSai Krishna Potthuri default: 322fa99e701SSai Krishna Potthuri ret = -ENOTSUPP; 3238b242ca7SSai Krishna Potthuri break; 3248b242ca7SSai Krishna Potthuri } 3258b242ca7SSai Krishna Potthuri 3268b242ca7SSai Krishna Potthuri if (ret) 3278b242ca7SSai Krishna Potthuri return ret; 3288b242ca7SSai Krishna Potthuri 3298b242ca7SSai Krishna Potthuri param = pinconf_to_config_param(*config); 3308b242ca7SSai Krishna Potthuri *config = pinconf_to_config_packed(param, arg); 3318b242ca7SSai Krishna Potthuri 3328b242ca7SSai Krishna Potthuri return 0; 3338b242ca7SSai Krishna Potthuri } 3348b242ca7SSai Krishna Potthuri 3358b242ca7SSai Krishna Potthuri /** 3368b242ca7SSai Krishna Potthuri * zynqmp_pinconf_cfg_set() - Set requested config for the pin 3378b242ca7SSai Krishna Potthuri * @pctldev: Pincontrol device pointer. 3388b242ca7SSai Krishna Potthuri * @pin: Pin number. 3398b242ca7SSai Krishna Potthuri * @configs: Configuration to set. 3408b242ca7SSai Krishna Potthuri * @num_configs: Number of configurations. 3418b242ca7SSai Krishna Potthuri * 3428b242ca7SSai Krishna Potthuri * Loop through all configurations and call firmware API 3438b242ca7SSai Krishna Potthuri * to set requested configurations for the pin. 3448b242ca7SSai Krishna Potthuri * 3458b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 3468b242ca7SSai Krishna Potthuri */ 3478b242ca7SSai Krishna Potthuri static int zynqmp_pinconf_cfg_set(struct pinctrl_dev *pctldev, 3488b242ca7SSai Krishna Potthuri unsigned int pin, unsigned long *configs, 3498b242ca7SSai Krishna Potthuri unsigned int num_configs) 3508b242ca7SSai Krishna Potthuri { 3518b242ca7SSai Krishna Potthuri int i, ret; 3528b242ca7SSai Krishna Potthuri 3538b242ca7SSai Krishna Potthuri for (i = 0; i < num_configs; i++) { 3548b242ca7SSai Krishna Potthuri unsigned int param = pinconf_to_config_param(configs[i]); 3558b242ca7SSai Krishna Potthuri unsigned int arg = pinconf_to_config_argument(configs[i]); 3568b242ca7SSai Krishna Potthuri unsigned int value; 3578b242ca7SSai Krishna Potthuri 3588b242ca7SSai Krishna Potthuri switch (param) { 3598b242ca7SSai Krishna Potthuri case PIN_CONFIG_SLEW_RATE: 3608b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_SLEW_RATE; 3618b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 3628b242ca7SSai Krishna Potthuri break; 3638b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_PULL_UP: 3648b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_PULL_CTRL; 3658b242ca7SSai Krishna Potthuri arg = PM_PINCTRL_BIAS_PULL_UP; 3668b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 3678b242ca7SSai Krishna Potthuri break; 3688b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_PULL_DOWN: 3698b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_PULL_CTRL; 3708b242ca7SSai Krishna Potthuri arg = PM_PINCTRL_BIAS_PULL_DOWN; 3718b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 3728b242ca7SSai Krishna Potthuri break; 3738b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_DISABLE: 3748b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_BIAS_STATUS; 3758b242ca7SSai Krishna Potthuri arg = PM_PINCTRL_BIAS_DISABLE; 3768b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 3778b242ca7SSai Krishna Potthuri break; 3788b242ca7SSai Krishna Potthuri case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 3798b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_SCHMITT_CMOS; 3808b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 3818b242ca7SSai Krishna Potthuri break; 3828b242ca7SSai Krishna Potthuri case PIN_CONFIG_DRIVE_STRENGTH: 3838b242ca7SSai Krishna Potthuri switch (arg) { 3848b242ca7SSai Krishna Potthuri case DRIVE_STRENGTH_2MA: 3858b242ca7SSai Krishna Potthuri value = PM_PINCTRL_DRIVE_STRENGTH_2MA; 3868b242ca7SSai Krishna Potthuri break; 3878b242ca7SSai Krishna Potthuri case DRIVE_STRENGTH_4MA: 3888b242ca7SSai Krishna Potthuri value = PM_PINCTRL_DRIVE_STRENGTH_4MA; 3898b242ca7SSai Krishna Potthuri break; 3908b242ca7SSai Krishna Potthuri case DRIVE_STRENGTH_8MA: 3918b242ca7SSai Krishna Potthuri value = PM_PINCTRL_DRIVE_STRENGTH_8MA; 3928b242ca7SSai Krishna Potthuri break; 3938b242ca7SSai Krishna Potthuri case DRIVE_STRENGTH_12MA: 3948b242ca7SSai Krishna Potthuri value = PM_PINCTRL_DRIVE_STRENGTH_12MA; 3958b242ca7SSai Krishna Potthuri break; 3968b242ca7SSai Krishna Potthuri default: 3978b242ca7SSai Krishna Potthuri /* Invalid drive strength */ 3988b242ca7SSai Krishna Potthuri dev_warn(pctldev->dev, 3998b242ca7SSai Krishna Potthuri "Invalid drive strength for pin %d\n", 4008b242ca7SSai Krishna Potthuri pin); 4018b242ca7SSai Krishna Potthuri return -EINVAL; 4028b242ca7SSai Krishna Potthuri } 4038b242ca7SSai Krishna Potthuri 4048b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH; 4058b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, value); 4068b242ca7SSai Krishna Potthuri break; 4078b242ca7SSai Krishna Potthuri case PIN_CONFIG_POWER_SOURCE: 4088b242ca7SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; 4098b242ca7SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_get_config(pin, param, &value); 4108b242ca7SSai Krishna Potthuri 4118b242ca7SSai Krishna Potthuri if (arg != value) 4128b242ca7SSai Krishna Potthuri dev_warn(pctldev->dev, 4138b242ca7SSai Krishna Potthuri "Invalid IO Standard requested for pin %d\n", 4148b242ca7SSai Krishna Potthuri pin); 4158b242ca7SSai Krishna Potthuri 4168b242ca7SSai Krishna Potthuri break; 4178b242ca7SSai Krishna Potthuri case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: 418*0516dd65SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_TRI_STATE; 419*0516dd65SSai Krishna Potthuri arg = PM_PINCTRL_TRI_STATE_ENABLE; 420*0516dd65SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 421*0516dd65SSai Krishna Potthuri break; 4228b242ca7SSai Krishna Potthuri case PIN_CONFIG_MODE_LOW_POWER: 4238b242ca7SSai Krishna Potthuri /* 4248b242ca7SSai Krishna Potthuri * These cases are mentioned in dts but configurable 4258b242ca7SSai Krishna Potthuri * registers are unknown. So falling through to ignore 4268b242ca7SSai Krishna Potthuri * boot time warnings as of now. 4278b242ca7SSai Krishna Potthuri */ 4288b242ca7SSai Krishna Potthuri ret = 0; 4298b242ca7SSai Krishna Potthuri break; 430*0516dd65SSai Krishna Potthuri case PIN_CONFIG_OUTPUT_ENABLE: 431*0516dd65SSai Krishna Potthuri param = PM_PINCTRL_CONFIG_TRI_STATE; 432*0516dd65SSai Krishna Potthuri arg = PM_PINCTRL_TRI_STATE_DISABLE; 433*0516dd65SSai Krishna Potthuri ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); 434*0516dd65SSai Krishna Potthuri break; 4358b242ca7SSai Krishna Potthuri default: 4368b242ca7SSai Krishna Potthuri dev_warn(pctldev->dev, 4378b242ca7SSai Krishna Potthuri "unsupported configuration parameter '%u'\n", 4388b242ca7SSai Krishna Potthuri param); 439fa99e701SSai Krishna Potthuri ret = -ENOTSUPP; 4408b242ca7SSai Krishna Potthuri break; 4418b242ca7SSai Krishna Potthuri } 4428b242ca7SSai Krishna Potthuri 4438b242ca7SSai Krishna Potthuri param = pinconf_to_config_param(configs[i]); 4448b242ca7SSai Krishna Potthuri arg = pinconf_to_config_argument(configs[i]); 4458b242ca7SSai Krishna Potthuri if (ret) 4468b242ca7SSai Krishna Potthuri dev_warn(pctldev->dev, 4478b242ca7SSai Krishna Potthuri "failed to set: pin %u param %u value %u\n", 4488b242ca7SSai Krishna Potthuri pin, param, arg); 4498b242ca7SSai Krishna Potthuri } 4508b242ca7SSai Krishna Potthuri 4518b242ca7SSai Krishna Potthuri return 0; 4528b242ca7SSai Krishna Potthuri } 4538b242ca7SSai Krishna Potthuri 4548b242ca7SSai Krishna Potthuri /** 4558b242ca7SSai Krishna Potthuri * zynqmp_pinconf_group_set() - Set requested config for the group 4568b242ca7SSai Krishna Potthuri * @pctldev: Pincontrol device pointer. 4578b242ca7SSai Krishna Potthuri * @selector: Group ID. 4588b242ca7SSai Krishna Potthuri * @configs: Configuration to set. 4598b242ca7SSai Krishna Potthuri * @num_configs: Number of configurations. 4608b242ca7SSai Krishna Potthuri * 4618b242ca7SSai Krishna Potthuri * Call function to set configs for each pin in the group. 4628b242ca7SSai Krishna Potthuri * 4638b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 4648b242ca7SSai Krishna Potthuri */ 4658b242ca7SSai Krishna Potthuri static int zynqmp_pinconf_group_set(struct pinctrl_dev *pctldev, 4668b242ca7SSai Krishna Potthuri unsigned int selector, 4678b242ca7SSai Krishna Potthuri unsigned long *configs, 4688b242ca7SSai Krishna Potthuri unsigned int num_configs) 4698b242ca7SSai Krishna Potthuri { 4708b242ca7SSai Krishna Potthuri int i, ret; 4718b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 4728b242ca7SSai Krishna Potthuri const struct zynqmp_pctrl_group *pgrp = &pctrl->groups[selector]; 4738b242ca7SSai Krishna Potthuri 4748b242ca7SSai Krishna Potthuri for (i = 0; i < pgrp->npins; i++) { 4758b242ca7SSai Krishna Potthuri ret = zynqmp_pinconf_cfg_set(pctldev, pgrp->pins[i], configs, 4768b242ca7SSai Krishna Potthuri num_configs); 4778b242ca7SSai Krishna Potthuri if (ret) 4788b242ca7SSai Krishna Potthuri return ret; 4798b242ca7SSai Krishna Potthuri } 4808b242ca7SSai Krishna Potthuri 4818b242ca7SSai Krishna Potthuri return 0; 4828b242ca7SSai Krishna Potthuri } 4838b242ca7SSai Krishna Potthuri 4848b242ca7SSai Krishna Potthuri static const struct pinconf_ops zynqmp_pinconf_ops = { 4858b242ca7SSai Krishna Potthuri .is_generic = true, 4868b242ca7SSai Krishna Potthuri .pin_config_get = zynqmp_pinconf_cfg_get, 4878b242ca7SSai Krishna Potthuri .pin_config_set = zynqmp_pinconf_cfg_set, 4888b242ca7SSai Krishna Potthuri .pin_config_group_set = zynqmp_pinconf_group_set, 4898b242ca7SSai Krishna Potthuri }; 4908b242ca7SSai Krishna Potthuri 4918b242ca7SSai Krishna Potthuri static struct pinctrl_desc zynqmp_desc = { 4928b242ca7SSai Krishna Potthuri .name = "zynqmp_pinctrl", 4938b242ca7SSai Krishna Potthuri .owner = THIS_MODULE, 4948b242ca7SSai Krishna Potthuri .pctlops = &zynqmp_pctrl_ops, 4958b242ca7SSai Krishna Potthuri .pmxops = &zynqmp_pinmux_ops, 4968b242ca7SSai Krishna Potthuri .confops = &zynqmp_pinconf_ops, 4978b242ca7SSai Krishna Potthuri }; 4988b242ca7SSai Krishna Potthuri 4998b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_get_function_groups(u32 fid, u32 index, u16 *groups) 5008b242ca7SSai Krishna Potthuri { 5018b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 5028b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 5038b242ca7SSai Krishna Potthuri int ret; 5048b242ca7SSai Krishna Potthuri 5058b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_FUNCTION_GROUPS; 5068b242ca7SSai Krishna Potthuri qdata.arg1 = fid; 5078b242ca7SSai Krishna Potthuri qdata.arg2 = index; 5088b242ca7SSai Krishna Potthuri 5098b242ca7SSai Krishna Potthuri ret = zynqmp_pm_query_data(qdata, payload); 5108b242ca7SSai Krishna Potthuri if (ret) 5118b242ca7SSai Krishna Potthuri return ret; 5128b242ca7SSai Krishna Potthuri 5138b242ca7SSai Krishna Potthuri memcpy(groups, &payload[1], PINCTRL_GET_FUNC_GROUPS_RESP_LEN); 5148b242ca7SSai Krishna Potthuri 515fa99e701SSai Krishna Potthuri return 0; 5168b242ca7SSai Krishna Potthuri } 5178b242ca7SSai Krishna Potthuri 5188b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_get_func_num_groups(u32 fid, unsigned int *ngroups) 5198b242ca7SSai Krishna Potthuri { 5208b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 5218b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 5228b242ca7SSai Krishna Potthuri int ret; 5238b242ca7SSai Krishna Potthuri 5248b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS; 5258b242ca7SSai Krishna Potthuri qdata.arg1 = fid; 5268b242ca7SSai Krishna Potthuri 5278b242ca7SSai Krishna Potthuri ret = zynqmp_pm_query_data(qdata, payload); 5288b242ca7SSai Krishna Potthuri if (ret) 5298b242ca7SSai Krishna Potthuri return ret; 5308b242ca7SSai Krishna Potthuri 5318b242ca7SSai Krishna Potthuri *ngroups = payload[1]; 5328b242ca7SSai Krishna Potthuri 533fa99e701SSai Krishna Potthuri return 0; 5348b242ca7SSai Krishna Potthuri } 5358b242ca7SSai Krishna Potthuri 5368b242ca7SSai Krishna Potthuri /** 5378b242ca7SSai Krishna Potthuri * zynqmp_pinctrl_prepare_func_groups() - prepare function and groups data 5388b242ca7SSai Krishna Potthuri * @dev: Device pointer. 5398b242ca7SSai Krishna Potthuri * @fid: Function ID. 5408b242ca7SSai Krishna Potthuri * @func: Function data. 5418b242ca7SSai Krishna Potthuri * @groups: Groups data. 5428b242ca7SSai Krishna Potthuri * 5438b242ca7SSai Krishna Potthuri * Query firmware to get group IDs for each function. Firmware returns 544fa99e701SSai Krishna Potthuri * group IDs. Based on the group index for the function, group names in 5458b242ca7SSai Krishna Potthuri * the function are stored. For example, the first group in "eth0" function 546fa99e701SSai Krishna Potthuri * is named as "eth0_0" and the second group as "eth0_1" and so on. 5478b242ca7SSai Krishna Potthuri * 5488b242ca7SSai Krishna Potthuri * Based on the group ID received from the firmware, function stores name of 5498b242ca7SSai Krishna Potthuri * the group for that group ID. For example, if "eth0" first group ID 5508b242ca7SSai Krishna Potthuri * is x, groups[x] name will be stored as "eth0_0". 5518b242ca7SSai Krishna Potthuri * 5528b242ca7SSai Krishna Potthuri * Once done for each function, each function would have its group names 553fa99e701SSai Krishna Potthuri * and each group would also have their names. 5548b242ca7SSai Krishna Potthuri * 5558b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 5568b242ca7SSai Krishna Potthuri */ 5578b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_prepare_func_groups(struct device *dev, u32 fid, 5588b242ca7SSai Krishna Potthuri struct zynqmp_pmux_function *func, 5598b242ca7SSai Krishna Potthuri struct zynqmp_pctrl_group *groups) 5608b242ca7SSai Krishna Potthuri { 5618b242ca7SSai Krishna Potthuri u16 resp[NUM_GROUPS_PER_RESP] = {0}; 5628b242ca7SSai Krishna Potthuri const char **fgroups; 563fa99e701SSai Krishna Potthuri int ret, index, i; 5648b242ca7SSai Krishna Potthuri 5658b242ca7SSai Krishna Potthuri fgroups = devm_kzalloc(dev, sizeof(*fgroups) * func->ngroups, GFP_KERNEL); 5668b242ca7SSai Krishna Potthuri if (!fgroups) 5678b242ca7SSai Krishna Potthuri return -ENOMEM; 5688b242ca7SSai Krishna Potthuri 5698b242ca7SSai Krishna Potthuri for (index = 0; index < func->ngroups; index += NUM_GROUPS_PER_RESP) { 5708b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_get_function_groups(fid, index, resp); 5718b242ca7SSai Krishna Potthuri if (ret) 5728b242ca7SSai Krishna Potthuri return ret; 5738b242ca7SSai Krishna Potthuri 5748b242ca7SSai Krishna Potthuri for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { 5758b242ca7SSai Krishna Potthuri if (resp[i] == NA_GROUP) 5768b242ca7SSai Krishna Potthuri goto done; 5778b242ca7SSai Krishna Potthuri 5788b242ca7SSai Krishna Potthuri if (resp[i] == RESERVED_GROUP) 5798b242ca7SSai Krishna Potthuri continue; 5808b242ca7SSai Krishna Potthuri 5818b242ca7SSai Krishna Potthuri fgroups[index + i] = devm_kasprintf(dev, GFP_KERNEL, 5828b242ca7SSai Krishna Potthuri "%s_%d_grp", 5838b242ca7SSai Krishna Potthuri func->name, 5848b242ca7SSai Krishna Potthuri index + i); 5858b242ca7SSai Krishna Potthuri if (!fgroups[index + i]) 5868b242ca7SSai Krishna Potthuri return -ENOMEM; 5878b242ca7SSai Krishna Potthuri 5888b242ca7SSai Krishna Potthuri groups[resp[i]].name = devm_kasprintf(dev, GFP_KERNEL, 5898b242ca7SSai Krishna Potthuri "%s_%d_grp", 5908b242ca7SSai Krishna Potthuri func->name, 5918b242ca7SSai Krishna Potthuri index + i); 5928b242ca7SSai Krishna Potthuri if (!groups[resp[i]].name) 5938b242ca7SSai Krishna Potthuri return -ENOMEM; 5948b242ca7SSai Krishna Potthuri } 5958b242ca7SSai Krishna Potthuri } 5968b242ca7SSai Krishna Potthuri done: 5978b242ca7SSai Krishna Potthuri func->groups = fgroups; 5988b242ca7SSai Krishna Potthuri 599fa99e701SSai Krishna Potthuri return 0; 6008b242ca7SSai Krishna Potthuri } 6018b242ca7SSai Krishna Potthuri 6028b242ca7SSai Krishna Potthuri static void zynqmp_pinctrl_get_function_name(u32 fid, char *name) 6038b242ca7SSai Krishna Potthuri { 6048b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 6058b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 6068b242ca7SSai Krishna Potthuri 6078b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_FUNCTION_NAME; 6088b242ca7SSai Krishna Potthuri qdata.arg1 = fid; 6098b242ca7SSai Krishna Potthuri 6108b242ca7SSai Krishna Potthuri /* 6118b242ca7SSai Krishna Potthuri * Name of the function is maximum 16 bytes and cannot 6128b242ca7SSai Krishna Potthuri * accommodate the return value in SMC buffers, hence ignoring 6138b242ca7SSai Krishna Potthuri * the return value for this specific qid. 6148b242ca7SSai Krishna Potthuri */ 6158b242ca7SSai Krishna Potthuri zynqmp_pm_query_data(qdata, payload); 6168b242ca7SSai Krishna Potthuri memcpy(name, payload, PINCTRL_GET_FUNC_NAME_RESP_LEN); 6178b242ca7SSai Krishna Potthuri } 6188b242ca7SSai Krishna Potthuri 6198b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_get_num_functions(unsigned int *nfuncs) 6208b242ca7SSai Krishna Potthuri { 6218b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 6228b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 6238b242ca7SSai Krishna Potthuri int ret; 6248b242ca7SSai Krishna Potthuri 6258b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_NUM_FUNCTIONS; 6268b242ca7SSai Krishna Potthuri 6278b242ca7SSai Krishna Potthuri ret = zynqmp_pm_query_data(qdata, payload); 6288b242ca7SSai Krishna Potthuri if (ret) 6298b242ca7SSai Krishna Potthuri return ret; 6308b242ca7SSai Krishna Potthuri 6318b242ca7SSai Krishna Potthuri *nfuncs = payload[1]; 6328b242ca7SSai Krishna Potthuri 633fa99e701SSai Krishna Potthuri return 0; 6348b242ca7SSai Krishna Potthuri } 6358b242ca7SSai Krishna Potthuri 6368b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_get_pin_groups(u32 pin, u32 index, u16 *groups) 6378b242ca7SSai Krishna Potthuri { 6388b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 6398b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 6408b242ca7SSai Krishna Potthuri int ret; 6418b242ca7SSai Krishna Potthuri 6428b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_PIN_GROUPS; 6438b242ca7SSai Krishna Potthuri qdata.arg1 = pin; 6448b242ca7SSai Krishna Potthuri qdata.arg2 = index; 6458b242ca7SSai Krishna Potthuri 6468b242ca7SSai Krishna Potthuri ret = zynqmp_pm_query_data(qdata, payload); 6478b242ca7SSai Krishna Potthuri if (ret) 6488b242ca7SSai Krishna Potthuri return ret; 6498b242ca7SSai Krishna Potthuri 6508b242ca7SSai Krishna Potthuri memcpy(groups, &payload[1], PINCTRL_GET_PIN_GROUPS_RESP_LEN); 6518b242ca7SSai Krishna Potthuri 652fa99e701SSai Krishna Potthuri return 0; 6538b242ca7SSai Krishna Potthuri } 6548b242ca7SSai Krishna Potthuri 6558b242ca7SSai Krishna Potthuri static void zynqmp_pinctrl_group_add_pin(struct zynqmp_pctrl_group *group, 6568b242ca7SSai Krishna Potthuri unsigned int pin) 6578b242ca7SSai Krishna Potthuri { 6588b242ca7SSai Krishna Potthuri group->pins[group->npins++] = pin; 6598b242ca7SSai Krishna Potthuri } 6608b242ca7SSai Krishna Potthuri 6618b242ca7SSai Krishna Potthuri /** 6628b242ca7SSai Krishna Potthuri * zynqmp_pinctrl_create_pin_groups() - assign pins to respective groups 6638b242ca7SSai Krishna Potthuri * @dev: Device pointer. 6648b242ca7SSai Krishna Potthuri * @groups: Groups data. 6658b242ca7SSai Krishna Potthuri * @pin: Pin number. 6668b242ca7SSai Krishna Potthuri * 6678b242ca7SSai Krishna Potthuri * Query firmware to get groups available for the given pin. 6688b242ca7SSai Krishna Potthuri * Based on the firmware response(group IDs for the pin), add 6698b242ca7SSai Krishna Potthuri * pin number to the respective group's pin array. 6708b242ca7SSai Krishna Potthuri * 671fa99e701SSai Krishna Potthuri * Once all pins are queries, each group would have its number 6728b242ca7SSai Krishna Potthuri * of pins and pin numbers data. 6738b242ca7SSai Krishna Potthuri * 6748b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 6758b242ca7SSai Krishna Potthuri */ 6768b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_create_pin_groups(struct device *dev, 6778b242ca7SSai Krishna Potthuri struct zynqmp_pctrl_group *groups, 6788b242ca7SSai Krishna Potthuri unsigned int pin) 6798b242ca7SSai Krishna Potthuri { 6808b242ca7SSai Krishna Potthuri u16 resp[NUM_GROUPS_PER_RESP] = {0}; 6818b242ca7SSai Krishna Potthuri int ret, i, index = 0; 6828b242ca7SSai Krishna Potthuri 6838b242ca7SSai Krishna Potthuri do { 6848b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_get_pin_groups(pin, index, resp); 6858b242ca7SSai Krishna Potthuri if (ret) 6868b242ca7SSai Krishna Potthuri return ret; 6878b242ca7SSai Krishna Potthuri 6888b242ca7SSai Krishna Potthuri for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { 6898b242ca7SSai Krishna Potthuri if (resp[i] == NA_GROUP) 6908b242ca7SSai Krishna Potthuri return ret; 6918b242ca7SSai Krishna Potthuri 6928b242ca7SSai Krishna Potthuri if (resp[i] == RESERVED_GROUP) 6938b242ca7SSai Krishna Potthuri continue; 6948b242ca7SSai Krishna Potthuri 6958b242ca7SSai Krishna Potthuri zynqmp_pinctrl_group_add_pin(&groups[resp[i]], pin); 6968b242ca7SSai Krishna Potthuri } 6978b242ca7SSai Krishna Potthuri index += NUM_GROUPS_PER_RESP; 6988b242ca7SSai Krishna Potthuri } while (index <= MAX_PIN_GROUPS); 6998b242ca7SSai Krishna Potthuri 700fa99e701SSai Krishna Potthuri return 0; 7018b242ca7SSai Krishna Potthuri } 7028b242ca7SSai Krishna Potthuri 7038b242ca7SSai Krishna Potthuri /** 7048b242ca7SSai Krishna Potthuri * zynqmp_pinctrl_prepare_group_pins() - prepare each group's pin data 7058b242ca7SSai Krishna Potthuri * @dev: Device pointer. 7068b242ca7SSai Krishna Potthuri * @groups: Groups data. 7078b242ca7SSai Krishna Potthuri * @ngroups: Number of groups. 7088b242ca7SSai Krishna Potthuri * 7098b242ca7SSai Krishna Potthuri * Prepare pin number and number of pins data for each pins. 7108b242ca7SSai Krishna Potthuri * 7118b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 7128b242ca7SSai Krishna Potthuri */ 7138b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_prepare_group_pins(struct device *dev, 7148b242ca7SSai Krishna Potthuri struct zynqmp_pctrl_group *groups, 7158b242ca7SSai Krishna Potthuri unsigned int ngroups) 7168b242ca7SSai Krishna Potthuri { 7178b242ca7SSai Krishna Potthuri unsigned int pin; 7188b242ca7SSai Krishna Potthuri int ret; 7198b242ca7SSai Krishna Potthuri 7208b242ca7SSai Krishna Potthuri for (pin = 0; pin < zynqmp_desc.npins; pin++) { 7218b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_create_pin_groups(dev, groups, pin); 7228b242ca7SSai Krishna Potthuri if (ret) 7238b242ca7SSai Krishna Potthuri return ret; 7248b242ca7SSai Krishna Potthuri } 7258b242ca7SSai Krishna Potthuri 7268b242ca7SSai Krishna Potthuri return 0; 7278b242ca7SSai Krishna Potthuri } 7288b242ca7SSai Krishna Potthuri 7298b242ca7SSai Krishna Potthuri /** 7308b242ca7SSai Krishna Potthuri * zynqmp_pinctrl_prepare_function_info() - prepare function info 7318b242ca7SSai Krishna Potthuri * @dev: Device pointer. 7328b242ca7SSai Krishna Potthuri * @pctrl: Pin control driver data. 7338b242ca7SSai Krishna Potthuri * 7348b242ca7SSai Krishna Potthuri * Query firmware for functions, groups and pin information and 7358b242ca7SSai Krishna Potthuri * prepare pin control driver data. 7368b242ca7SSai Krishna Potthuri * 7378b242ca7SSai Krishna Potthuri * Query number of functions and number of function groups (number 738fa99e701SSai Krishna Potthuri * of groups in the given function) to allocate required memory buffers 7398b242ca7SSai Krishna Potthuri * for functions and groups. Once buffers are allocated to store 7408b242ca7SSai Krishna Potthuri * functions and groups data, query and store required information 7418b242ca7SSai Krishna Potthuri * (number of groups and group names for each function, number of 7428b242ca7SSai Krishna Potthuri * pins and pin numbers for each group). 7438b242ca7SSai Krishna Potthuri * 7448b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 7458b242ca7SSai Krishna Potthuri */ 7468b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_prepare_function_info(struct device *dev, 7478b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl) 7488b242ca7SSai Krishna Potthuri { 7498b242ca7SSai Krishna Potthuri struct zynqmp_pmux_function *funcs; 7508b242ca7SSai Krishna Potthuri struct zynqmp_pctrl_group *groups; 7518b242ca7SSai Krishna Potthuri int ret, i; 7528b242ca7SSai Krishna Potthuri 7538b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_get_num_functions(&pctrl->nfuncs); 7548b242ca7SSai Krishna Potthuri if (ret) 7558b242ca7SSai Krishna Potthuri return ret; 7568b242ca7SSai Krishna Potthuri 7578b242ca7SSai Krishna Potthuri funcs = devm_kzalloc(dev, sizeof(*funcs) * pctrl->nfuncs, GFP_KERNEL); 7588b242ca7SSai Krishna Potthuri if (!funcs) 7598b242ca7SSai Krishna Potthuri return -ENOMEM; 7608b242ca7SSai Krishna Potthuri 7618b242ca7SSai Krishna Potthuri for (i = 0; i < pctrl->nfuncs; i++) { 7628b242ca7SSai Krishna Potthuri zynqmp_pinctrl_get_function_name(i, funcs[i].name); 7638b242ca7SSai Krishna Potthuri 7648b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_get_func_num_groups(i, &funcs[i].ngroups); 7658b242ca7SSai Krishna Potthuri if (ret) 7668b242ca7SSai Krishna Potthuri return ret; 7678b242ca7SSai Krishna Potthuri 7688b242ca7SSai Krishna Potthuri pctrl->ngroups += funcs[i].ngroups; 7698b242ca7SSai Krishna Potthuri } 7708b242ca7SSai Krishna Potthuri 7718b242ca7SSai Krishna Potthuri groups = devm_kzalloc(dev, sizeof(*groups) * pctrl->ngroups, GFP_KERNEL); 7728b242ca7SSai Krishna Potthuri if (!groups) 7738b242ca7SSai Krishna Potthuri return -ENOMEM; 7748b242ca7SSai Krishna Potthuri 7758b242ca7SSai Krishna Potthuri for (i = 0; i < pctrl->nfuncs; i++) { 7768b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_prepare_func_groups(dev, i, &funcs[i], 7778b242ca7SSai Krishna Potthuri groups); 7788b242ca7SSai Krishna Potthuri if (ret) 7798b242ca7SSai Krishna Potthuri return ret; 7808b242ca7SSai Krishna Potthuri } 7818b242ca7SSai Krishna Potthuri 7828b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_prepare_group_pins(dev, groups, pctrl->ngroups); 7838b242ca7SSai Krishna Potthuri if (ret) 7848b242ca7SSai Krishna Potthuri return ret; 7858b242ca7SSai Krishna Potthuri 7868b242ca7SSai Krishna Potthuri pctrl->funcs = funcs; 7878b242ca7SSai Krishna Potthuri pctrl->groups = groups; 7888b242ca7SSai Krishna Potthuri 789fa99e701SSai Krishna Potthuri return 0; 7908b242ca7SSai Krishna Potthuri } 7918b242ca7SSai Krishna Potthuri 7928b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_get_num_pins(unsigned int *npins) 7938b242ca7SSai Krishna Potthuri { 7948b242ca7SSai Krishna Potthuri struct zynqmp_pm_query_data qdata = {0}; 7958b242ca7SSai Krishna Potthuri u32 payload[PAYLOAD_ARG_CNT]; 7968b242ca7SSai Krishna Potthuri int ret; 7978b242ca7SSai Krishna Potthuri 7988b242ca7SSai Krishna Potthuri qdata.qid = PM_QID_PINCTRL_GET_NUM_PINS; 7998b242ca7SSai Krishna Potthuri 8008b242ca7SSai Krishna Potthuri ret = zynqmp_pm_query_data(qdata, payload); 8018b242ca7SSai Krishna Potthuri if (ret) 8028b242ca7SSai Krishna Potthuri return ret; 8038b242ca7SSai Krishna Potthuri 8048b242ca7SSai Krishna Potthuri *npins = payload[1]; 8058b242ca7SSai Krishna Potthuri 806fa99e701SSai Krishna Potthuri return 0; 8078b242ca7SSai Krishna Potthuri } 8088b242ca7SSai Krishna Potthuri 8098b242ca7SSai Krishna Potthuri /** 8108b242ca7SSai Krishna Potthuri * zynqmp_pinctrl_prepare_pin_desc() - prepare pin description info 8118b242ca7SSai Krishna Potthuri * @dev: Device pointer. 8128b242ca7SSai Krishna Potthuri * @zynqmp_pins: Pin information. 8138b242ca7SSai Krishna Potthuri * @npins: Number of pins. 8148b242ca7SSai Krishna Potthuri * 8158b242ca7SSai Krishna Potthuri * Query number of pins information from firmware and prepare pin 8168b242ca7SSai Krishna Potthuri * description containing pin number and pin name. 8178b242ca7SSai Krishna Potthuri * 8188b242ca7SSai Krishna Potthuri * Return: 0 on success else error code. 8198b242ca7SSai Krishna Potthuri */ 8208b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev, 8218b242ca7SSai Krishna Potthuri const struct pinctrl_pin_desc 8228b242ca7SSai Krishna Potthuri **zynqmp_pins, 8238b242ca7SSai Krishna Potthuri unsigned int *npins) 8248b242ca7SSai Krishna Potthuri { 8258b242ca7SSai Krishna Potthuri struct pinctrl_pin_desc *pins, *pin; 8268b242ca7SSai Krishna Potthuri int ret; 8278b242ca7SSai Krishna Potthuri int i; 8288b242ca7SSai Krishna Potthuri 8298b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_get_num_pins(npins); 8308b242ca7SSai Krishna Potthuri if (ret) 8318b242ca7SSai Krishna Potthuri return ret; 8328b242ca7SSai Krishna Potthuri 8338b242ca7SSai Krishna Potthuri pins = devm_kzalloc(dev, sizeof(*pins) * *npins, GFP_KERNEL); 8348b242ca7SSai Krishna Potthuri if (!pins) 8358b242ca7SSai Krishna Potthuri return -ENOMEM; 8368b242ca7SSai Krishna Potthuri 8378b242ca7SSai Krishna Potthuri for (i = 0; i < *npins; i++) { 8388b242ca7SSai Krishna Potthuri pin = &pins[i]; 8398b242ca7SSai Krishna Potthuri pin->number = i; 840500c77eeSGerhard Engleder pin->name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", 841500c77eeSGerhard Engleder ZYNQMP_PIN_PREFIX, i); 842500c77eeSGerhard Engleder if (!pin->name) 843500c77eeSGerhard Engleder return -ENOMEM; 8448b242ca7SSai Krishna Potthuri } 8458b242ca7SSai Krishna Potthuri 8468b242ca7SSai Krishna Potthuri *zynqmp_pins = pins; 8478b242ca7SSai Krishna Potthuri 8488b242ca7SSai Krishna Potthuri return 0; 8498b242ca7SSai Krishna Potthuri } 8508b242ca7SSai Krishna Potthuri 8518b242ca7SSai Krishna Potthuri static int zynqmp_pinctrl_probe(struct platform_device *pdev) 8528b242ca7SSai Krishna Potthuri { 8538b242ca7SSai Krishna Potthuri struct zynqmp_pinctrl *pctrl; 8548b242ca7SSai Krishna Potthuri int ret; 8558b242ca7SSai Krishna Potthuri 8568b242ca7SSai Krishna Potthuri pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); 8578b242ca7SSai Krishna Potthuri if (!pctrl) 8588b242ca7SSai Krishna Potthuri return -ENOMEM; 8598b242ca7SSai Krishna Potthuri 8608b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_prepare_pin_desc(&pdev->dev, 8618b242ca7SSai Krishna Potthuri &zynqmp_desc.pins, 8628b242ca7SSai Krishna Potthuri &zynqmp_desc.npins); 8638b242ca7SSai Krishna Potthuri if (ret) { 864fa99e701SSai Krishna Potthuri dev_err(&pdev->dev, "pin desc prepare fail with %d\n", ret); 8658b242ca7SSai Krishna Potthuri return ret; 8668b242ca7SSai Krishna Potthuri } 8678b242ca7SSai Krishna Potthuri 8688b242ca7SSai Krishna Potthuri ret = zynqmp_pinctrl_prepare_function_info(&pdev->dev, pctrl); 8698b242ca7SSai Krishna Potthuri if (ret) { 870fa99e701SSai Krishna Potthuri dev_err(&pdev->dev, "function info prepare fail with %d\n", ret); 8718b242ca7SSai Krishna Potthuri return ret; 8728b242ca7SSai Krishna Potthuri } 8738b242ca7SSai Krishna Potthuri 874fa99e701SSai Krishna Potthuri pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &zynqmp_desc, pctrl); 8758b242ca7SSai Krishna Potthuri if (IS_ERR(pctrl->pctrl)) 8768b242ca7SSai Krishna Potthuri return PTR_ERR(pctrl->pctrl); 8778b242ca7SSai Krishna Potthuri 8788b242ca7SSai Krishna Potthuri platform_set_drvdata(pdev, pctrl); 8798b242ca7SSai Krishna Potthuri 8808b242ca7SSai Krishna Potthuri return ret; 8818b242ca7SSai Krishna Potthuri } 8828b242ca7SSai Krishna Potthuri 8838b242ca7SSai Krishna Potthuri static const struct of_device_id zynqmp_pinctrl_of_match[] = { 8848b242ca7SSai Krishna Potthuri { .compatible = "xlnx,zynqmp-pinctrl" }, 8858b242ca7SSai Krishna Potthuri { } 8868b242ca7SSai Krishna Potthuri }; 8878b242ca7SSai Krishna Potthuri MODULE_DEVICE_TABLE(of, zynqmp_pinctrl_of_match); 8888b242ca7SSai Krishna Potthuri 8898b242ca7SSai Krishna Potthuri static struct platform_driver zynqmp_pinctrl_driver = { 8908b242ca7SSai Krishna Potthuri .driver = { 8918b242ca7SSai Krishna Potthuri .name = "zynqmp-pinctrl", 8928b242ca7SSai Krishna Potthuri .of_match_table = zynqmp_pinctrl_of_match, 8938b242ca7SSai Krishna Potthuri }, 8948b242ca7SSai Krishna Potthuri .probe = zynqmp_pinctrl_probe, 8958b242ca7SSai Krishna Potthuri }; 8968b242ca7SSai Krishna Potthuri module_platform_driver(zynqmp_pinctrl_driver); 8978b242ca7SSai Krishna Potthuri 8988b242ca7SSai Krishna Potthuri MODULE_AUTHOR("Sai Krishna Potthuri <lakshmi.sai.krishna.potthuri@xilinx.com>"); 8998b242ca7SSai Krishna Potthuri MODULE_DESCRIPTION("ZynqMP Pin Controller Driver"); 9008b242ca7SSai Krishna Potthuri MODULE_LICENSE("GPL v2"); 901