linux/drivers/pinctrl/pinctrl-pxa3xx.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/pinctrl/pinctrl-pxa3xx.c
   3 *
   4 *  This program is free software; you can redistribute it and/or modify
   5 *  it under the terms of the GNU General Public License version 2 as
   6 *  publishhed by the Free Software Foundation.
   7 *
   8 *  Copyright (C) 2011, Marvell Technology Group Ltd.
   9 *
  10 *  Author: Haojian Zhuang <haojian.zhuang@marvell.com>
  11 *
  12 */
  13
  14#include <linux/module.h>
  15#include <linux/device.h>
  16#include <linux/io.h>
  17#include <linux/platform_device.h>
  18#include <linux/slab.h>
  19#include "pinctrl-pxa3xx.h"
  20
  21static struct pinctrl_gpio_range pxa3xx_pinctrl_gpio_range = {
  22        .name           = "PXA3xx GPIO",
  23        .id             = 0,
  24        .base           = 0,
  25        .pin_base       = 0,
  26};
  27
  28static int pxa3xx_get_groups_count(struct pinctrl_dev *pctrldev)
  29{
  30        struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
  31
  32        return info->num_grps;
  33}
  34
  35static const char *pxa3xx_get_group_name(struct pinctrl_dev *pctrldev,
  36                                         unsigned selector)
  37{
  38        struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
  39
  40        return info->grps[selector].name;
  41}
  42
  43static int pxa3xx_get_group_pins(struct pinctrl_dev *pctrldev,
  44                                 unsigned selector,
  45                                 const unsigned **pins,
  46                                 unsigned *num_pins)
  47{
  48        struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
  49
  50        *pins = info->grps[selector].pins;
  51        *num_pins = info->grps[selector].npins;
  52        return 0;
  53}
  54
  55static struct pinctrl_ops pxa3xx_pctrl_ops = {
  56        .get_groups_count = pxa3xx_get_groups_count,
  57        .get_group_name = pxa3xx_get_group_name,
  58        .get_group_pins = pxa3xx_get_group_pins,
  59};
  60
  61static int pxa3xx_pmx_get_funcs_count(struct pinctrl_dev *pctrldev)
  62{
  63        struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
  64
  65        return info->num_funcs;
  66}
  67
  68static const char *pxa3xx_pmx_get_func_name(struct pinctrl_dev *pctrldev,
  69                                            unsigned func)
  70{
  71        struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
  72        return info->funcs[func].name;
  73}
  74
  75static int pxa3xx_pmx_get_groups(struct pinctrl_dev *pctrldev, unsigned func,
  76                                 const char * const **groups,
  77                                 unsigned * const num_groups)
  78{
  79        struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
  80        *groups = info->funcs[func].groups;
  81        *num_groups = info->funcs[func].num_groups;
  82        return 0;
  83}
  84
  85/* Return function number. If failure, return negative value. */
  86static int match_mux(struct pxa3xx_mfp_pin *mfp, unsigned mux)
  87{
  88        int i;
  89        for (i = 0; i < PXA3xx_MAX_MUX; i++) {
  90                if (mfp->func[i] == mux)
  91                        break;
  92        }
  93        if (i >= PXA3xx_MAX_MUX)
  94                return -EINVAL;
  95        return i;
  96}
  97
  98/* check whether current pin configuration is valid. Negative for failure */
  99static int match_group_mux(struct pxa3xx_pin_group *grp,
 100                           struct pxa3xx_pinmux_info *info,
 101                           unsigned mux)
 102{
 103        int i, pin, ret = 0;
 104        for (i = 0; i < grp->npins; i++) {
 105                pin = grp->pins[i];
 106                ret = match_mux(&info->mfp[pin], mux);
 107                if (ret < 0) {
 108                        dev_err(info->dev, "Can't find mux %d on pin%d\n",
 109                                mux, pin);
 110                        break;
 111                }
 112        }
 113        return ret;
 114}
 115
 116static int pxa3xx_pmx_enable(struct pinctrl_dev *pctrldev, unsigned func,
 117                             unsigned group)
 118{
 119        struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
 120        struct pxa3xx_pin_group *pin_grp = &info->grps[group];
 121        unsigned int data;
 122        int i, mfpr, pin, pin_func;
 123
 124        if (!pin_grp->npins ||
 125                (match_group_mux(pin_grp, info, pin_grp->mux) < 0)) {
 126                dev_err(info->dev, "Failed to set the pin group: %d\n", group);
 127                return -EINVAL;
 128        }
 129        for (i = 0; i < pin_grp->npins; i++) {
 130                pin = pin_grp->pins[i];
 131                pin_func = match_mux(&info->mfp[pin], pin_grp->mux);
 132                mfpr = info->mfp[pin].mfpr;
 133                data = readl_relaxed(info->virt_base + mfpr);
 134                data &= ~MFPR_FUNC_MASK;
 135                data |= pin_func;
 136                writel_relaxed(data, info->virt_base + mfpr);
 137        }
 138        return 0;
 139}
 140
 141static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev,
 142                                   struct pinctrl_gpio_range *range,
 143                                   unsigned pin)
 144{
 145        struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
 146        unsigned int data;
 147        int pin_func, mfpr;
 148
 149        pin_func = match_mux(&info->mfp[pin], PXA3xx_MUX_GPIO);
 150        if (pin_func < 0) {
 151                dev_err(info->dev, "No GPIO function on pin%d (%s)\n",
 152                        pin, info->pads[pin].name);
 153                return -EINVAL;
 154        }
 155        mfpr = info->mfp[pin].mfpr;
 156        /* write gpio function into mfpr register */
 157        data = readl_relaxed(info->virt_base + mfpr) & ~MFPR_FUNC_MASK;
 158        data |= pin_func;
 159        writel_relaxed(data, info->virt_base + mfpr);
 160        return 0;
 161}
 162
 163static struct pinmux_ops pxa3xx_pmx_ops = {
 164        .get_functions_count    = pxa3xx_pmx_get_funcs_count,
 165        .get_function_name      = pxa3xx_pmx_get_func_name,
 166        .get_function_groups    = pxa3xx_pmx_get_groups,
 167        .enable                 = pxa3xx_pmx_enable,
 168        .gpio_request_enable    = pxa3xx_pmx_request_gpio,
 169};
 170
 171int pxa3xx_pinctrl_register(struct platform_device *pdev,
 172                            struct pxa3xx_pinmux_info *info)
 173{
 174        struct pinctrl_desc *desc;
 175        struct resource *res;
 176        int ret = 0;
 177
 178        if (!info || !info->cputype)
 179                return -EINVAL;
 180        desc = info->desc;
 181        desc->pins = info->pads;
 182        desc->npins = info->num_pads;
 183        desc->pctlops = &pxa3xx_pctrl_ops;
 184        desc->pmxops = &pxa3xx_pmx_ops;
 185        info->dev = &pdev->dev;
 186        pxa3xx_pinctrl_gpio_range.npins = info->num_gpio;
 187
 188        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 189        if (!res)
 190                return -ENOENT;
 191        info->phy_base = res->start;
 192        info->phy_size = resource_size(res);
 193        info->virt_base = ioremap(info->phy_base, info->phy_size);
 194        if (!info->virt_base)
 195                return -ENOMEM;
 196        info->pctrl = pinctrl_register(desc, &pdev->dev, info);
 197        if (!info->pctrl) {
 198                dev_err(&pdev->dev, "failed to register PXA pinmux driver\n");
 199                ret = -EINVAL;
 200                goto err;
 201        }
 202        pinctrl_add_gpio_range(info->pctrl, &pxa3xx_pinctrl_gpio_range);
 203        platform_set_drvdata(pdev, info);
 204        return 0;
 205err:
 206        iounmap(info->virt_base);
 207        return ret;
 208}
 209
 210int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
 211{
 212        struct pxa3xx_pinmux_info *info = platform_get_drvdata(pdev);
 213
 214        pinctrl_unregister(info->pctrl);
 215        iounmap(info->virt_base);
 216        platform_set_drvdata(pdev, NULL);
 217        return 0;
 218}
 219
 220static int __init pxa3xx_pinctrl_init(void)
 221{
 222        pr_info("pxa3xx-pinctrl: PXA3xx pinctrl driver initializing\n");
 223        return 0;
 224}
 225core_initcall_sync(pxa3xx_pinctrl_init);
 226
 227static void __exit pxa3xx_pinctrl_exit(void)
 228{
 229}
 230module_exit(pxa3xx_pinctrl_exit);
 231
 232MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
 233MODULE_DESCRIPTION("PXA3xx pin control driver");
 234MODULE_LICENSE("GPL v2");
 235
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.