diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 09:28:03 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 09:28:03 -0700 | 
| commit | dfab34aa61a0f8c14a67d7b4c1dae28e57ba592d (patch) | |
| tree | 581fd4d7394b838acb70c3c2e5d585b5b8a86b0d /drivers/pinctrl/pinctrl-imx.c | |
| parent | a7726350e06401929eac0aa0677a5467106565fc (diff) | |
| parent | 88cf9c5e494795a53ec360d0b38f483a6d4e508f (diff) | |
| download | olio-linux-3.10-dfab34aa61a0f8c14a67d7b4c1dae28e57ba592d.tar.xz olio-linux-3.10-dfab34aa61a0f8c14a67d7b4c1dae28e57ba592d.zip  | |
Merge tag 'dt-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC device-tree updates from Olof Johansson:
 "Part 1 of device-tree updates for 3.10.  The bulk of the churn in this
  branch is due to i.MX moving from C-defined pin control over to device
  tree, which is a one-time conversion that will allow greater
  flexibility down the road.
  Besides that, there's PCI-e bindings for Marvell mvebu platforms and a
  handful of cleanups to tegra due to the new include file functionality
  of the device tree compiler"
* tag 'dt-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (113 commits)
  arm: mvebu: PCIe Device Tree informations for Armada XP GP
  arm: mvebu: PCIe Device Tree informations for Armada 370 DB
  arm: mvebu: PCIe Device Tree informations for Armada 370 Mirabox
  arm: mvebu: PCIe Device Tree informations for Armada XP DB
  arm: mvebu: PCIe Device Tree informations for OpenBlocks AX3-4
  arm: mvebu: add PCIe Device Tree informations for Armada XP
  arm: mvebu: add PCIe Device Tree informations for Armada 370
  ARM: sunxi: unify osc24M_fixed and osc24M
  arm: vt8500: Add SDHC support to WM8505 DT
  ARM: dts: Add a 64 bits version of the skeleton device tree
  ARM: mvebu: Add Device Bus and CFI flash memory support to defconfig
  ARM: mvebu: Add support for NOR flash device on Openblocks AX3 board
  ARM: mvebu: Add support for NOR flash device on Armada XP-GP board
  ARM: mvebu: Add Device Bus support for Armada 370/XP SoC
  ARM: dts: imx6dl-wandboard: Add USB Host support
  ARM: dts: imx51 cpu node
  ARM: dts: Add missing imx27-phytec-phycore dtb target
  ARM: dts: Add NFC support for i.MX27 Phytec PCM038 module
  ARM: i.MX51: Add PATA support
  ARM: dts: Add initial support for Wandboard Dual-Lite
  ...
Diffstat (limited to 'drivers/pinctrl/pinctrl-imx.c')
| -rw-r--r-- | drivers/pinctrl/pinctrl-imx.c | 126 | 
1 files changed, 47 insertions, 79 deletions
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c index 0ef190449ea..4fcfff9243b 100644 --- a/drivers/pinctrl/pinctrl-imx.c +++ b/drivers/pinctrl/pinctrl-imx.c @@ -54,32 +54,6 @@ struct imx_pinctrl {  	const struct imx_pinctrl_soc_info *info;  }; -static const struct imx_pin_reg *imx_find_pin_reg( -				const struct imx_pinctrl_soc_info *info, -				unsigned pin, bool is_mux, unsigned mux) -{ -	const struct imx_pin_reg *pin_reg = NULL; -	int i; - -	for (i = 0; i < info->npin_regs; i++) { -		pin_reg = &info->pin_regs[i]; -		if (pin_reg->pid != pin) -			continue; -		if (!is_mux) -			break; -		else if (pin_reg->mux_mode == (mux & IMX_MUX_MASK)) -			break; -	} - -	if (i == info->npin_regs) { -		dev_err(info->dev, "Pin(%s): unable to find pin reg map\n", -			info->pins[pin].name); -		return NULL; -	} - -	return pin_reg; -} -  static const inline struct imx_pin_group *imx_pinctrl_find_group_by_name(  				const struct imx_pinctrl_soc_info *info,  				const char *name) @@ -223,7 +197,8 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,  	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);  	const struct imx_pinctrl_soc_info *info = ipctl->info;  	const struct imx_pin_reg *pin_reg; -	const unsigned *pins, *mux; +	const unsigned *pins, *mux, *input_val; +	u16 *input_reg;  	unsigned int npins, pin_id;  	int i; @@ -234,18 +209,17 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,  	pins = info->groups[group].pins;  	npins = info->groups[group].npins;  	mux = info->groups[group].mux_mode; +	input_val = info->groups[group].input_val; +	input_reg = info->groups[group].input_reg; -	WARN_ON(!pins || !npins || !mux); +	WARN_ON(!pins || !npins || !mux || !input_val || !input_reg);  	dev_dbg(ipctl->dev, "enable function %s group %s\n",  		info->functions[selector].name, info->groups[group].name);  	for (i = 0; i < npins; i++) {  		pin_id = pins[i]; - -		pin_reg = imx_find_pin_reg(info, pin_id, 1, mux[i]); -		if (!pin_reg) -			return -EINVAL; +		pin_reg = &info->pin_regs[pin_id];  		if (!pin_reg->mux_reg) {  			dev_err(ipctl->dev, "Pin(%s) does not support mux function\n", @@ -258,11 +232,11 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,  			pin_reg->mux_reg, mux[i]);  		/* some pins also need select input setting, set it if found */ -		if (pin_reg->input_reg) { -			writel(pin_reg->input_val, ipctl->base + pin_reg->input_reg); +		if (input_reg[i]) { +			writel(input_val[i], ipctl->base + input_reg[i]);  			dev_dbg(ipctl->dev,  				"==>select_input: offset 0x%x val 0x%x\n", -				pin_reg->input_reg, pin_reg->input_val); +				input_reg[i], input_val[i]);  		}  	} @@ -311,11 +285,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,  {  	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);  	const struct imx_pinctrl_soc_info *info = ipctl->info; -	const struct imx_pin_reg *pin_reg; - -	pin_reg = imx_find_pin_reg(info, pin_id, 0, 0); -	if (!pin_reg) -		return -EINVAL; +	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];  	if (!pin_reg->conf_reg) {  		dev_err(info->dev, "Pin(%s) does not support config function\n", @@ -333,11 +303,7 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,  {  	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);  	const struct imx_pinctrl_soc_info *info = ipctl->info; -	const struct imx_pin_reg *pin_reg; - -	pin_reg = imx_find_pin_reg(info, pin_id, 0, 0); -	if (!pin_reg) -		return -EINVAL; +	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];  	if (!pin_reg->conf_reg) {  		dev_err(info->dev, "Pin(%s) does not support config function\n", @@ -360,10 +326,9 @@ static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,  {  	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);  	const struct imx_pinctrl_soc_info *info = ipctl->info; -	const struct imx_pin_reg *pin_reg; +	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];  	unsigned long config; -	pin_reg = imx_find_pin_reg(info, pin_id, 0, 0);  	if (!pin_reg || !pin_reg->conf_reg) {  		seq_printf(s, "N/A");  		return; @@ -411,29 +376,20 @@ static struct pinctrl_desc imx_pinctrl_desc = {  	.owner = THIS_MODULE,  }; -/* decode pin id and mux from pin function id got from device tree*/ -static int imx_pinctrl_get_pin_id_and_mux(const struct imx_pinctrl_soc_info *info, -				unsigned int pin_func_id, unsigned int *pin_id, -				unsigned int *mux) -{ -	if (pin_func_id > info->npin_regs) -		return -EINVAL; - -	*pin_id = info->pin_regs[pin_func_id].pid; -	*mux = info->pin_regs[pin_func_id].mux_mode; - -	return 0; -} +/* + * Each pin represented in fsl,pins consists of 5 u32 PIN_FUNC_ID and + * 1 u32 CONFIG, so 24 types in total for each pin. + */ +#define FSL_PIN_SIZE 24  static int imx_pinctrl_parse_groups(struct device_node *np,  				    struct imx_pin_group *grp,  				    struct imx_pinctrl_soc_info *info,  				    u32 index)  { -	unsigned int pin_func_id; -	int ret, size; +	int size;  	const __be32 *list; -	int i, j; +	int i;  	u32 config;  	dev_dbg(info->dev, "group(%d): %s\n", index, np->name); @@ -447,32 +403,40 @@ static int imx_pinctrl_parse_groups(struct device_node *np,  	 */  	list = of_get_property(np, "fsl,pins", &size);  	/* we do not check return since it's safe node passed down */ -	size /= sizeof(*list); -	if (!size || size % 2) { -		dev_err(info->dev, "wrong pins number or pins and configs should be pairs\n"); +	if (!size || size % FSL_PIN_SIZE) { +		dev_err(info->dev, "Invalid fsl,pins property\n");  		return -EINVAL;  	} -	grp->npins = size / 2; +	grp->npins = size / FSL_PIN_SIZE;  	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),  				GFP_KERNEL);  	grp->mux_mode = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),  				GFP_KERNEL); +	grp->input_reg = devm_kzalloc(info->dev, grp->npins * sizeof(u16), +				GFP_KERNEL); +	grp->input_val = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), +				GFP_KERNEL);  	grp->configs = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned long),  				GFP_KERNEL); -	for (i = 0, j = 0; i < size; i += 2, j++) { -		pin_func_id = be32_to_cpu(*list++); -		ret = imx_pinctrl_get_pin_id_and_mux(info, pin_func_id, -					&grp->pins[j], &grp->mux_mode[j]); -		if (ret) { -			dev_err(info->dev, "get invalid pin function id\n"); -			return -EINVAL; -		} +	for (i = 0; i < grp->npins; i++) { +		u32 mux_reg = be32_to_cpu(*list++); +		u32 conf_reg = be32_to_cpu(*list++); +		unsigned int pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4; +		struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id]; + +		grp->pins[i] = pin_id; +		pin_reg->mux_reg = mux_reg; +		pin_reg->conf_reg = conf_reg; +		grp->input_reg[i] = be32_to_cpu(*list++); +		grp->mux_mode[i] = be32_to_cpu(*list++); +		grp->input_val[i] = be32_to_cpu(*list++); +  		/* SION bit is in mux register */  		config = be32_to_cpu(*list++);  		if (config & IMX_PAD_SION) -			grp->mux_mode[j] |= IOMUXC_CONFIG_SION; -		grp->configs[j] = config & ~IMX_PAD_SION; +			grp->mux_mode[i] |= IOMUXC_CONFIG_SION; +		grp->configs[i] = config & ~IMX_PAD_SION;  	}  #ifdef DEBUG @@ -568,8 +532,7 @@ int imx_pinctrl_probe(struct platform_device *pdev,  	struct resource *res;  	int ret; -	if (!info || !info->pins || !info->npins -		  || !info->pin_regs || !info->npin_regs) { +	if (!info || !info->pins || !info->npins) {  		dev_err(&pdev->dev, "wrong pinctrl info\n");  		return -EINVAL;  	} @@ -580,6 +543,11 @@ int imx_pinctrl_probe(struct platform_device *pdev,  	if (!ipctl)  		return -ENOMEM; +	info->pin_regs = devm_kzalloc(&pdev->dev, sizeof(*info->pin_regs) * +				      info->npins, GFP_KERNEL); +	if (!info->pin_regs) +		return -ENOMEM; +  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res)  		return -ENOENT;  |