linux/arch/arm/mach-imx/iomux-imx31.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
   4 * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
   5 * Copyright (C) 2009 by Valentin Longchamp <valentin.longchamp@epfl.ch>
   6 */
   7#include <linux/gpio.h>
   8#include <linux/module.h>
   9#include <linux/spinlock.h>
  10#include <linux/io.h>
  11#include <linux/kernel.h>
  12
  13#include "hardware.h"
  14#include "iomux-mx3.h"
  15
  16/*
  17 * IOMUX register (base) addresses
  18 */
  19#define IOMUX_BASE      MX31_IO_ADDRESS(MX31_IOMUXC_BASE_ADDR)
  20#define IOMUXINT_OBS1   (IOMUX_BASE + 0x000)
  21#define IOMUXINT_OBS2   (IOMUX_BASE + 0x004)
  22#define IOMUXGPR        (IOMUX_BASE + 0x008)
  23#define IOMUXSW_MUX_CTL (IOMUX_BASE + 0x00C)
  24#define IOMUXSW_PAD_CTL (IOMUX_BASE + 0x154)
  25
  26static DEFINE_SPINLOCK(gpio_mux_lock);
  27
  28#define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3)
  29
  30static DECLARE_BITMAP(mxc_pin_alloc_map, NB_PORTS * 32);
  31/*
  32 * set the mode for a IOMUX pin.
  33 */
  34void mxc_iomux_mode(unsigned int pin_mode)
  35{
  36        u32 field;
  37        u32 l;
  38        u32 mode;
  39        void __iomem *reg;
  40
  41        reg = IOMUXSW_MUX_CTL + (pin_mode & IOMUX_REG_MASK);
  42        field = pin_mode & 0x3;
  43        mode = (pin_mode & IOMUX_MODE_MASK) >> IOMUX_MODE_SHIFT;
  44
  45        spin_lock(&gpio_mux_lock);
  46
  47        l = imx_readl(reg);
  48        l &= ~(0xff << (field * 8));
  49        l |= mode << (field * 8);
  50        imx_writel(l, reg);
  51
  52        spin_unlock(&gpio_mux_lock);
  53}
  54
  55/*
  56 * This function configures the pad value for a IOMUX pin.
  57 */
  58void mxc_iomux_set_pad(enum iomux_pins pin, u32 config)
  59{
  60        u32 field, l;
  61        void __iomem *reg;
  62
  63        pin &= IOMUX_PADNUM_MASK;
  64        reg = IOMUXSW_PAD_CTL + (pin + 2) / 3 * 4;
  65        field = (pin + 2) % 3;
  66
  67        pr_debug("%s: reg offset = 0x%x, field = %d\n",
  68                        __func__, (pin + 2) / 3, field);
  69
  70        spin_lock(&gpio_mux_lock);
  71
  72        l = imx_readl(reg);
  73        l &= ~(0x1ff << (field * 10));
  74        l |= config << (field * 10);
  75        imx_writel(l, reg);
  76
  77        spin_unlock(&gpio_mux_lock);
  78}
  79
  80/*
  81 * allocs a single pin:
  82 *      - reserves the pin so that it is not claimed by another driver
  83 *      - setups the iomux according to the configuration
  84 */
  85int mxc_iomux_alloc_pin(unsigned int pin, const char *label)
  86{
  87        unsigned pad = pin & IOMUX_PADNUM_MASK;
  88
  89        if (pad >= (PIN_MAX + 1)) {
  90                printk(KERN_ERR "mxc_iomux: Attempt to request nonexistent pin %u for \"%s\"\n",
  91                        pad, label ? label : "?");
  92                return -EINVAL;
  93        }
  94
  95        if (test_and_set_bit(pad, mxc_pin_alloc_map)) {
  96                printk(KERN_ERR "mxc_iomux: pin %u already used. Allocation for \"%s\" failed\n",
  97                        pad, label ? label : "?");
  98                return -EBUSY;
  99        }
 100        mxc_iomux_mode(pin);
 101
 102        return 0;
 103}
 104
 105int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
 106                const char *label)
 107{
 108        const unsigned int *p = pin_list;
 109        int i;
 110        int ret = -EINVAL;
 111
 112        for (i = 0; i < count; i++) {
 113                ret = mxc_iomux_alloc_pin(*p, label);
 114                if (ret)
 115                        goto setup_error;
 116                p++;
 117        }
 118        return 0;
 119
 120setup_error:
 121        mxc_iomux_release_multiple_pins(pin_list, i);
 122        return ret;
 123}
 124
 125void mxc_iomux_release_pin(unsigned int pin)
 126{
 127        unsigned pad = pin & IOMUX_PADNUM_MASK;
 128
 129        if (pad < (PIN_MAX + 1))
 130                clear_bit(pad, mxc_pin_alloc_map);
 131}
 132
 133void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count)
 134{
 135        const unsigned int *p = pin_list;
 136        int i;
 137
 138        for (i = 0; i < count; i++) {
 139                mxc_iomux_release_pin(*p);
 140                p++;
 141        }
 142}
 143
 144/*
 145 * This function enables/disables the general purpose function for a particular
 146 * signal.
 147 */
 148void mxc_iomux_set_gpr(enum iomux_gp_func gp, bool en)
 149{
 150        u32 l;
 151
 152        spin_lock(&gpio_mux_lock);
 153        l = imx_readl(IOMUXGPR);
 154        if (en)
 155                l |= gp;
 156        else
 157                l &= ~gp;
 158
 159        imx_writel(l, IOMUXGPR);
 160        spin_unlock(&gpio_mux_lock);
 161}
 162