1ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng/* 2ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * Core driver for the imx pin controller 3ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * 4ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * Copyright (C) 2012 Freescale Semiconductor, Inc. 5ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * Copyright (C) 2012 Linaro Ltd. 6ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * 7ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * Author: Dong Aisheng <dong.aisheng@linaro.org> 8ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * 9ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * This program is free software; you can redistribute it and/or modify 10ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * it under the terms of the GNU General Public License as published by 11ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * the Free Software Foundation; either version 2 of the License, or 12ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * (at your option) any later version. 13ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng */ 14ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 15ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include <linux/err.h> 16ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include <linux/init.h> 17ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include <linux/io.h> 18ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include <linux/module.h> 19ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include <linux/of.h> 20ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include <linux/of_device.h> 21ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include <linux/pinctrl/machine.h> 22ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include <linux/pinctrl/pinconf.h> 23ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include <linux/pinctrl/pinctrl.h> 24ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include <linux/pinctrl/pinmux.h> 25ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include <linux/slab.h> 26ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 27edad3b2a57082f6166b4f13445f70e8d3fc415fbLinus Walleij#include "../core.h" 28ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#include "pinctrl-imx.h" 29ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 30ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng/* The bits in CONFIG cell defined in binding doc*/ 31ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#define IMX_NO_PAD_CTL 0x80000000 /* no pin config need */ 32ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng#define IMX_PAD_SION 0x40000000 /* set SION */ 33ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 34ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng/** 35ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * @dev: a pointer back to containing device 36ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * @base: the offset to the controller in virtual memory 37ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng */ 38ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstruct imx_pinctrl { 39ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct device *dev; 40ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct pinctrl_dev *pctl; 41ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng void __iomem *base; 42ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info; 43ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng}; 44ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 45ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic const inline struct imx_pin_group *imx_pinctrl_find_group_by_name( 46ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info, 47ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const char *name) 48ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 49ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pin_group *grp = NULL; 50ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng int i; 51ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 52ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng for (i = 0; i < info->ngroups; i++) { 53ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (!strcmp(info->groups[i].name, name)) { 54ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng grp = &info->groups[i]; 55ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng break; 56ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 57ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 58ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 59ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return grp; 60ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 61ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 62ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic int imx_get_groups_count(struct pinctrl_dev *pctldev) 63ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 64ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 65ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 66ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 67ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return info->ngroups; 68ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 69ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 70ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic const char *imx_get_group_name(struct pinctrl_dev *pctldev, 71ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng unsigned selector) 72ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 73ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 74ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 75ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 76ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return info->groups[selector].name; 77ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 78ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 79ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic int imx_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, 80ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const unsigned **pins, 81ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng unsigned *npins) 82ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 83ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 84ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 85ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 86ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (selector >= info->ngroups) 87ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -EINVAL; 88ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 898f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer *pins = info->groups[selector].pin_ids; 90ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng *npins = info->groups[selector].npins; 91ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 92ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return 0; 93ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 94ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 95ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic void imx_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, 96ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng unsigned offset) 97ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 98ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng seq_printf(s, "%s", dev_name(pctldev->dev)); 99ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 100ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 101ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic int imx_dt_node_to_map(struct pinctrl_dev *pctldev, 102ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct device_node *np, 103ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct pinctrl_map **map, unsigned *num_maps) 104ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 105ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 106ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 107ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pin_group *grp; 108ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct pinctrl_map *new_map; 109ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct device_node *parent; 110ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng int map_num = 1; 11118071610677fc491a226fa6d5471c89a26ce670dHui Wang int i, j; 112ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 113ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng /* 114ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * first find the group of this node and check if we need create 115ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * config maps for pins 116ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng */ 117ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng grp = imx_pinctrl_find_group_by_name(info, np->name); 118ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (!grp) { 119ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_err(info->dev, "unable to find group for node %s\n", 120ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng np->name); 121ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -EINVAL; 122ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 123ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 124ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng for (i = 0; i < grp->npins; i++) { 1258f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer if (!(grp->pins[i].config & IMX_NO_PAD_CTL)) 126ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng map_num++; 127ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 128ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 129ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng new_map = kmalloc(sizeof(struct pinctrl_map) * map_num, GFP_KERNEL); 130ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (!new_map) 131ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -ENOMEM; 132ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 133ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng *map = new_map; 134ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng *num_maps = map_num; 135ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 136ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng /* create mux map */ 137ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng parent = of_get_parent(np); 138c71157c54a4f86e4f355dc6952268e8536013502Devendra Naga if (!parent) { 139c71157c54a4f86e4f355dc6952268e8536013502Devendra Naga kfree(new_map); 140ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -EINVAL; 141c71157c54a4f86e4f355dc6952268e8536013502Devendra Naga } 142ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng new_map[0].type = PIN_MAP_TYPE_MUX_GROUP; 143ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng new_map[0].data.mux.function = parent->name; 144ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng new_map[0].data.mux.group = np->name; 145ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng of_node_put(parent); 146ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 147ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng /* create config map */ 148ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng new_map++; 14918071610677fc491a226fa6d5471c89a26ce670dHui Wang for (i = j = 0; i < grp->npins; i++) { 1508f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer if (!(grp->pins[i].config & IMX_NO_PAD_CTL)) { 15118071610677fc491a226fa6d5471c89a26ce670dHui Wang new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN; 15218071610677fc491a226fa6d5471c89a26ce670dHui Wang new_map[j].data.configs.group_or_pin = 1538f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer pin_get_name(pctldev, grp->pins[i].pin); 1548f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer new_map[j].data.configs.configs = &grp->pins[i].config; 15518071610677fc491a226fa6d5471c89a26ce670dHui Wang new_map[j].data.configs.num_configs = 1; 15618071610677fc491a226fa6d5471c89a26ce670dHui Wang j++; 157ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 158ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 159ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 160ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n", 16167695f2eae210b0631fb92cf5649d0454953e230Dong Aisheng (*map)->data.mux.function, (*map)->data.mux.group, map_num); 162ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 163ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return 0; 164ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 165ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 166ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic void imx_dt_free_map(struct pinctrl_dev *pctldev, 167ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct pinctrl_map *map, unsigned num_maps) 168ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 1693a86a5f8abb33956446ae31b1e9c149d7b2d1d21Devendra Naga kfree(map); 170ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 171ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 172022ab148d28e8466e45d28552224e3029f1cccd8Laurent Pinchartstatic const struct pinctrl_ops imx_pctrl_ops = { 173ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .get_groups_count = imx_get_groups_count, 174ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .get_group_name = imx_get_group_name, 175ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .get_group_pins = imx_get_group_pins, 176ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .pin_dbg_show = imx_pin_dbg_show, 177ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .dt_node_to_map = imx_dt_node_to_map, 178ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .dt_free_map = imx_dt_free_map, 179ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 180ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng}; 181ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 18203e9f0cac5da6af85758276cb4624caf5911f2b9Linus Walleijstatic int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, 18303e9f0cac5da6af85758276cb4624caf5911f2b9Linus Walleij unsigned group) 184ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 185ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 186ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 187ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pin_reg *pin_reg; 188ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng unsigned int npins, pin_id; 189ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng int i; 1908f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer struct imx_pin_group *grp; 191ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 192ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng /* 193ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * Configure the mux mode for each pin in the group for a specific 194ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * function. 195ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng */ 1968f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer grp = &info->groups[group]; 1978f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer npins = grp->npins; 198ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 199ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_dbg(ipctl->dev, "enable function %s group %s\n", 2008f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer info->functions[selector].name, grp->name); 201ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 202ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng for (i = 0; i < npins; i++) { 2038f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer struct imx_pin *pin = &grp->pins[i]; 2048f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer pin_id = pin->pin; 205e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo pin_reg = &info->pin_regs[pin_id]; 206ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 2073dac1918a4912cea9375e76cb3916b751cef22dbStefan Agner if (pin_reg->mux_reg == -1) { 208ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_err(ipctl->dev, "Pin(%s) does not support mux function\n", 209ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng info->pins[pin_id].name); 210ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -EINVAL; 211ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 212ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 213bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu if (info->flags & SHARE_MUX_CONF_REG) { 214bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu u32 reg; 215bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu reg = readl(ipctl->base + pin_reg->mux_reg); 216bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu reg &= ~(0x7 << 20); 2178f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer reg |= (pin->mux_mode << 20); 218bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu writel(reg, ipctl->base + pin_reg->mux_reg); 219bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu } else { 2208f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer writel(pin->mux_mode, ipctl->base + pin_reg->mux_reg); 221bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu } 222ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n", 2238f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer pin_reg->mux_reg, pin->mux_mode); 224ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 22594176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo /* 22694176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * If the select input value begins with 0xff, it's a quirky 22794176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * select input and the value should be interpreted as below. 22894176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * 31 23 15 7 0 22994176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * | 0xff | shift | width | select | 23094176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * It's used to work around the problem that the select 23194176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * input for some pin is not implemented in the select 23294176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * input register but in some general purpose register. 23394176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * We encode the select input value, width and shift of 23494176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * the bit field into input_val cell of pin function ID 23594176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * in device tree, and then decode them here for setting 23694176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * up the select input bits in general purpose register. 23794176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo */ 2388f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer if (pin->input_val >> 24 == 0xff) { 2398f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer u32 val = pin->input_val; 24094176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo u8 select = val & 0xff; 24194176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo u8 width = (val >> 8) & 0xff; 24294176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo u8 shift = (val >> 16) & 0xff; 24394176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo u32 mask = ((1 << width) - 1) << shift; 24494176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo /* 24594176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * The input_reg[i] here is actually some IOMUXC general 24694176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * purpose register, not regular select input register. 24794176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo */ 248a3183c60e3e9be7abd830ebed904491625e07d2ePeter Chen val = readl(ipctl->base + pin->input_reg); 24994176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo val &= ~mask; 25094176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo val |= select << shift; 251a3183c60e3e9be7abd830ebed904491625e07d2ePeter Chen writel(val, ipctl->base + pin->input_reg); 252a3183c60e3e9be7abd830ebed904491625e07d2ePeter Chen } else if (pin->input_reg) { 25394176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo /* 25494176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * Regular select input register can never be at offset 25594176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo * 0, and we only print register value for regular case. 25694176faf279ba96394f77cde62b1fdb8304ed30dShawn Guo */ 2578f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer writel(pin->input_val, ipctl->base + pin->input_reg); 258ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_dbg(ipctl->dev, 259ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng "==>select_input: offset 0x%x val 0x%x\n", 2608f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer pin->input_reg, pin->input_val); 261ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 262ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 263ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 264ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return 0; 265ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 266ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 267ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic int imx_pmx_get_funcs_count(struct pinctrl_dev *pctldev) 268ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 269ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 270ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 271ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 272ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return info->nfunctions; 273ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 274ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 275ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic const char *imx_pmx_get_func_name(struct pinctrl_dev *pctldev, 276ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng unsigned selector) 277ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 278ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 279ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 280ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 281ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return info->functions[selector].name; 282ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 283ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 284ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, 285ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const char * const **groups, 286ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng unsigned * const num_groups) 287ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 288ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 289ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 290ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 291ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng *groups = info->functions[selector].groups; 292ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng *num_groups = info->functions[selector].num_groups; 293ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 294ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return 0; 295ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 296ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 297022ab148d28e8466e45d28552224e3029f1cccd8Laurent Pinchartstatic const struct pinmux_ops imx_pmx_ops = { 298ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .get_functions_count = imx_pmx_get_funcs_count, 299ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .get_function_name = imx_pmx_get_func_name, 300ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .get_function_groups = imx_pmx_get_groups, 30103e9f0cac5da6af85758276cb4624caf5911f2b9Linus Walleij .set_mux = imx_pmx_set, 302ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng}; 303ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 304ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic int imx_pinconf_get(struct pinctrl_dev *pctldev, 305ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng unsigned pin_id, unsigned long *config) 306ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 307ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 308ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 309e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id]; 310ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 3113dac1918a4912cea9375e76cb3916b751cef22dbStefan Agner if (pin_reg->conf_reg == -1) { 312ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_err(info->dev, "Pin(%s) does not support config function\n", 313ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng info->pins[pin_id].name); 314ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -EINVAL; 315ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 316ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 317ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng *config = readl(ipctl->base + pin_reg->conf_reg); 318ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 319bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu if (info->flags & SHARE_MUX_CONF_REG) 320bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu *config &= 0xffff; 321bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu 322ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return 0; 323ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 324ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 325ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic int imx_pinconf_set(struct pinctrl_dev *pctldev, 32603b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin unsigned pin_id, unsigned long *configs, 32703b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin unsigned num_configs) 328ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 329ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 330ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 331e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id]; 33203b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin int i; 333ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 3343dac1918a4912cea9375e76cb3916b751cef22dbStefan Agner if (pin_reg->conf_reg == -1) { 335ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_err(info->dev, "Pin(%s) does not support config function\n", 336ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng info->pins[pin_id].name); 337ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -EINVAL; 338ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 339ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 340ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_dbg(ipctl->dev, "pinconf set pin %s\n", 341ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng info->pins[pin_id].name); 342ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 34303b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin for (i = 0; i < num_configs; i++) { 34403b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin if (info->flags & SHARE_MUX_CONF_REG) { 34503b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin u32 reg; 34603b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin reg = readl(ipctl->base + pin_reg->conf_reg); 34703b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin reg &= ~0xffff; 34803b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin reg |= configs[i]; 34903b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin writel(reg, ipctl->base + pin_reg->conf_reg); 35003b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin } else { 35103b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin writel(configs[i], ipctl->base + pin_reg->conf_reg); 35203b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin } 35303b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n", 35403b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin pin_reg->conf_reg, configs[i]); 35503b054e9696c3cbd3d5905ec96da15acd0a2fe8dSherman Yin } /* for each config */ 356ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 357ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return 0; 358ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 359ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 360ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev, 361ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct seq_file *s, unsigned pin_id) 362ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 363ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 364ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 365e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id]; 366ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng unsigned long config; 367ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 368ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (!pin_reg || !pin_reg->conf_reg) { 369ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng seq_printf(s, "N/A"); 370ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return; 371ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 372ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 373ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng config = readl(ipctl->base + pin_reg->conf_reg); 374ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng seq_printf(s, "0x%lx", config); 375ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 376ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 377ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, 378ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct seq_file *s, unsigned group) 379ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 380ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); 381ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const struct imx_pinctrl_soc_info *info = ipctl->info; 382ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pin_group *grp; 383ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng unsigned long config; 384ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng const char *name; 385ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng int i, ret; 386ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 387ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (group > info->ngroups) 388ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return; 389ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 390ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng seq_printf(s, "\n"); 391ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng grp = &info->groups[group]; 392ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng for (i = 0; i < grp->npins; i++) { 3938f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer struct imx_pin *pin = &grp->pins[i]; 3948f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer name = pin_get_name(pctldev, pin->pin); 3958f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer ret = imx_pinconf_get(pctldev, pin->pin, &config); 396ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (ret) 397ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return; 398ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng seq_printf(s, "%s: 0x%lx", name, config); 399ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 400ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 401ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 402022ab148d28e8466e45d28552224e3029f1cccd8Laurent Pinchartstatic const struct pinconf_ops imx_pinconf_ops = { 403ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .pin_config_get = imx_pinconf_get, 404ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .pin_config_set = imx_pinconf_set, 405ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .pin_config_dbg_show = imx_pinconf_dbg_show, 406ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .pin_config_group_dbg_show = imx_pinconf_group_dbg_show, 407ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng}; 408ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 409ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aishengstatic struct pinctrl_desc imx_pinctrl_desc = { 410ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .pctlops = &imx_pctrl_ops, 411ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .pmxops = &imx_pmx_ops, 412ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .confops = &imx_pinconf_ops, 413ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng .owner = THIS_MODULE, 414ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng}; 415ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 416e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo/* 417e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo * Each pin represented in fsl,pins consists of 5 u32 PIN_FUNC_ID and 418e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo * 1 u32 CONFIG, so 24 types in total for each pin. 419e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo */ 420e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo#define FSL_PIN_SIZE 24 421bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu#define SHARE_FSL_PIN_SIZE 20 422ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 423150632b09aadf1996f5cb6c0c2620d63a01fe2deGreg Kroah-Hartmanstatic int imx_pinctrl_parse_groups(struct device_node *np, 424150632b09aadf1996f5cb6c0c2620d63a01fe2deGreg Kroah-Hartman struct imx_pin_group *grp, 425150632b09aadf1996f5cb6c0c2620d63a01fe2deGreg Kroah-Hartman struct imx_pinctrl_soc_info *info, 426150632b09aadf1996f5cb6c0c2620d63a01fe2deGreg Kroah-Hartman u32 index) 427ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 428bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu int size, pin_size; 429a695145b9c4225eeadf56c3caf37cb3b525a32d4Richard Zhao const __be32 *list; 430e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo int i; 431ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng u32 config; 432ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 433ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_dbg(info->dev, "group(%d): %s\n", index, np->name); 434ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 435bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu if (info->flags & SHARE_MUX_CONF_REG) 436bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu pin_size = SHARE_FSL_PIN_SIZE; 437bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu else 438bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu pin_size = FSL_PIN_SIZE; 439ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng /* Initialise group */ 440ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng grp->name = np->name; 441ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 442ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng /* 443ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * the binding format is fsl,pins = <PIN_FUNC_ID CONFIG ...>, 444ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng * do sanity check and calculate pins number 445ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng */ 446ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng list = of_get_property(np, "fsl,pins", &size); 4471bf1fea95ff9161fafccbcac76b37bbadc924bd0Sascha Hauer if (!list) { 4481bf1fea95ff9161fafccbcac76b37bbadc924bd0Sascha Hauer dev_err(info->dev, "no fsl,pins property in node %s\n", np->full_name); 4491bf1fea95ff9161fafccbcac76b37bbadc924bd0Sascha Hauer return -EINVAL; 4501bf1fea95ff9161fafccbcac76b37bbadc924bd0Sascha Hauer } 4511bf1fea95ff9161fafccbcac76b37bbadc924bd0Sascha Hauer 452ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng /* we do not check return since it's safe node passed down */ 453bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu if (!size || size % pin_size) { 45401312513c4a48bdd4dbbea07716bd2dcd5d11c87Sascha Hauer dev_err(info->dev, "Invalid fsl,pins property in node %s\n", np->full_name); 455ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -EINVAL; 456ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 457ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 458bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu grp->npins = size / pin_size; 4598f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(struct imx_pin), 460ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng GFP_KERNEL); 4618f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer grp->pin_ids = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), 462ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng GFP_KERNEL); 4638f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer if (!grp->pins || ! grp->pin_ids) 4648f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer return -ENOMEM; 4658f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer 466e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo for (i = 0; i < grp->npins; i++) { 467e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo u32 mux_reg = be32_to_cpu(*list++); 468bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu u32 conf_reg; 469bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu unsigned int pin_id; 470bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu struct imx_pin_reg *pin_reg; 4718f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer struct imx_pin *pin = &grp->pins[i]; 472e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo 473bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu if (info->flags & SHARE_MUX_CONF_REG) 474bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu conf_reg = mux_reg; 475bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu else 476bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu conf_reg = be32_to_cpu(*list++); 477bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu 478bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4; 479bf5a530971afbe959348af4d84d17636108e6abfJingchang Lu pin_reg = &info->pin_regs[pin_id]; 4808f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer pin->pin = pin_id; 4818f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer grp->pin_ids[i] = pin_id; 482e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo pin_reg->mux_reg = mux_reg; 483e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo pin_reg->conf_reg = conf_reg; 4848f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer pin->input_reg = be32_to_cpu(*list++); 4858f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer pin->mux_mode = be32_to_cpu(*list++); 4868f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer pin->input_val = be32_to_cpu(*list++); 487e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo 488ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng /* SION bit is in mux register */ 489ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng config = be32_to_cpu(*list++); 490ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (config & IMX_PAD_SION) 4918f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer pin->mux_mode |= IOMUXC_CONFIG_SION; 4928f903f8a342e466f3da33b21ae60f1b11626b81aSascha Hauer pin->config = config & ~IMX_PAD_SION; 493ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 49408b519534e8c9a2bbf26db3e2dbab81e40b91705Fabio Estevam dev_dbg(info->dev, "%s: 0x%x 0x%08lx", info->pins[pin_id].name, 495406044695fb286110324491f26f3e05048488809Sascha Hauer pin->mux_mode, pin->config); 496406044695fb286110324491f26f3e05048488809Sascha Hauer } 4973a86a5f8abb33956446ae31b1e9c149d7b2d1d21Devendra Naga 498ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return 0; 499ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 500ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 501150632b09aadf1996f5cb6c0c2620d63a01fe2deGreg Kroah-Hartmanstatic int imx_pinctrl_parse_functions(struct device_node *np, 502150632b09aadf1996f5cb6c0c2620d63a01fe2deGreg Kroah-Hartman struct imx_pinctrl_soc_info *info, 503150632b09aadf1996f5cb6c0c2620d63a01fe2deGreg Kroah-Hartman u32 index) 504ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 505ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct device_node *child; 506ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pmx_func *func; 507ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pin_group *grp; 508ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng static u32 grp_index; 509ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng u32 i = 0; 510ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 511ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name); 512ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 513ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng func = &info->functions[index]; 514ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 515ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng /* Initialise function */ 516ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng func->name = np->name; 517ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng func->num_groups = of_get_child_count(np); 5189eedfd688cb267d0fee06f68cbbddaf94423482eRickard Strandqvist if (func->num_groups == 0) { 51901312513c4a48bdd4dbbea07716bd2dcd5d11c87Sascha Hauer dev_err(info->dev, "no groups defined in %s\n", np->full_name); 520ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -EINVAL; 521ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 522ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng func->groups = devm_kzalloc(info->dev, 523ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng func->num_groups * sizeof(char *), GFP_KERNEL); 524ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 525ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng for_each_child_of_node(np, child) { 526ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng func->groups[i] = child->name; 527ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng grp = &info->groups[grp_index++]; 5285e13762cf8e5a4998c3a80d2265f0c3b3277854eSascha Hauer imx_pinctrl_parse_groups(child, grp, info, i++); 529ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 530ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 531ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return 0; 532ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 533ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 534150632b09aadf1996f5cb6c0c2620d63a01fe2deGreg Kroah-Hartmanstatic int imx_pinctrl_probe_dt(struct platform_device *pdev, 535ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl_soc_info *info) 536ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 537ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct device_node *np = pdev->dev.of_node; 538ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct device_node *child; 539ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng u32 nfuncs = 0; 540ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng u32 i = 0; 541ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 542ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (!np) 543ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -ENODEV; 544ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 545ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng nfuncs = of_get_child_count(np); 546ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (nfuncs <= 0) { 547ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_err(&pdev->dev, "no functions defined\n"); 548ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -EINVAL; 549ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 550ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 551ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng info->nfunctions = nfuncs; 552ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng info->functions = devm_kzalloc(&pdev->dev, nfuncs * sizeof(struct imx_pmx_func), 553ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng GFP_KERNEL); 554ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (!info->functions) 555ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -ENOMEM; 556ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 557ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng info->ngroups = 0; 558ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng for_each_child_of_node(np, child) 559ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng info->ngroups += of_get_child_count(child); 560ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct imx_pin_group), 561ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng GFP_KERNEL); 562ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (!info->groups) 563ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -ENOMEM; 564ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 5657ea46e0f9df44ce3dea5a54f7c182f98eeef7beeSascha Hauer for_each_child_of_node(np, child) 5667ea46e0f9df44ce3dea5a54f7c182f98eeef7beeSascha Hauer imx_pinctrl_parse_functions(child, info, i++); 567ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 568ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return 0; 569ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 570ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 571150632b09aadf1996f5cb6c0c2620d63a01fe2deGreg Kroah-Hartmanint imx_pinctrl_probe(struct platform_device *pdev, 572150632b09aadf1996f5cb6c0c2620d63a01fe2deGreg Kroah-Hartman struct imx_pinctrl_soc_info *info) 573ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 574ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl; 575ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct resource *res; 576ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng int ret; 577ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 578e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo if (!info || !info->pins || !info->npins) { 579ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_err(&pdev->dev, "wrong pinctrl info\n"); 580ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -EINVAL; 581ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 582ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng info->dev = &pdev->dev; 583ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 584ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng /* Create state holders etc for this driver */ 585ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng ipctl = devm_kzalloc(&pdev->dev, sizeof(*ipctl), GFP_KERNEL); 586ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (!ipctl) 587ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -ENOMEM; 588ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 5893dac1918a4912cea9375e76cb3916b751cef22dbStefan Agner info->pin_regs = devm_kmalloc(&pdev->dev, sizeof(*info->pin_regs) * 590e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo info->npins, GFP_KERNEL); 591e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo if (!info->pin_regs) 592e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo return -ENOMEM; 5933dac1918a4912cea9375e76cb3916b751cef22dbStefan Agner memset(info->pin_regs, 0xff, sizeof(*info->pin_regs) * info->npins); 594e16415313c9b00b1adc313e85c2c8a81febe0b98Shawn Guo 595ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 5969e0c1fb29a7c257a31c321c2437617b6b4d66168Thierry Reding ipctl->base = devm_ioremap_resource(&pdev->dev, res); 5979e0c1fb29a7c257a31c321c2437617b6b4d66168Thierry Reding if (IS_ERR(ipctl->base)) 5989e0c1fb29a7c257a31c321c2437617b6b4d66168Thierry Reding return PTR_ERR(ipctl->base); 599ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 600ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng imx_pinctrl_desc.name = dev_name(&pdev->dev); 601ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng imx_pinctrl_desc.pins = info->pins; 602ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng imx_pinctrl_desc.npins = info->npins; 603ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 604ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng ret = imx_pinctrl_probe_dt(pdev, info); 605ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (ret) { 606ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_err(&pdev->dev, "fail to probe dt properties\n"); 607ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return ret; 608ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 609ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 610ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng ipctl->info = info; 611ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng ipctl->dev = info->dev; 612ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng platform_set_drvdata(pdev, ipctl); 613ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng ipctl->pctl = pinctrl_register(&imx_pinctrl_desc, &pdev->dev, ipctl); 614ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng if (!ipctl->pctl) { 615ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_err(&pdev->dev, "could not register IMX pinctrl driver\n"); 616ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return -EINVAL; 617ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng } 618ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 619ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng dev_info(&pdev->dev, "initialized IMX pinctrl driver\n"); 620ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 621ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return 0; 622ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 623ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 624f90f54b3f3c4d1c9168d5f8e97c6ac5b9ad25f5eBill Pembertonint imx_pinctrl_remove(struct platform_device *pdev) 625ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng{ 626ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng struct imx_pinctrl *ipctl = platform_get_drvdata(pdev); 627ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 628ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng pinctrl_unregister(ipctl->pctl); 629ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng 630ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng return 0; 631ae75ff8145384000e27eaa805c12e6971e3bec45Dong Aisheng} 632