linux/arch/arm/mach-imx/iomux-v1.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * arch/arm/plat-mxc/iomux-v1.c
   4 *
   5 * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
   6 * Copyright (C) 2009 Uwe Kleine-Koenig, Pengutronix
   7 *
   8 * Common code for i.MX1, i.MX21 and i.MX27
   9 */
  10
  11#include <linux/errno.h>
  12#include <linux/init.h>
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/string.h>
  16#include <linux/gpio.h>
  17
  18#include <asm/mach/map.h>
  19
  20#include "hardware.h"
  21#include "iomux-v1.h"
  22
  23static void __iomem *imx_iomuxv1_baseaddr;
  24static unsigned imx_iomuxv1_numports;
  25
  26static inline unsigned long imx_iomuxv1_readl(unsigned offset)
  27{
  28        return imx_readl(imx_iomuxv1_baseaddr + offset);
  29}
  30
  31static inline void imx_iomuxv1_writel(unsigned long val, unsigned offset)
  32{
  33        imx_writel(val, imx_iomuxv1_baseaddr + offset);
  34}
  35
  36static inline void imx_iomuxv1_rmwl(unsigned offset,
  37                unsigned long mask, unsigned long value)
  38{
  39        unsigned long reg = imx_iomuxv1_readl(offset);
  40
  41        reg &= ~mask;
  42        reg |= value;
  43
  44        imx_iomuxv1_writel(reg, offset);
  45}
  46
  47static inline void imx_iomuxv1_set_puen(
  48                unsigned int port, unsigned int pin, int on)
  49{
  50        unsigned long mask = 1 << pin;
  51
  52        imx_iomuxv1_rmwl(MXC_PUEN(port), mask, on ? mask : 0);
  53}
  54
  55static inline void imx_iomuxv1_set_ddir(
  56                unsigned int port, unsigned int pin, int out)
  57{
  58        unsigned long mask = 1 << pin;
  59
  60        imx_iomuxv1_rmwl(MXC_DDIR(port), mask, out ? mask : 0);
  61}
  62
  63static inline void imx_iomuxv1_set_gpr(
  64                unsigned int port, unsigned int pin, int af)
  65{
  66        unsigned long mask = 1 << pin;
  67
  68        imx_iomuxv1_rmwl(MXC_GPR(port), mask, af ? mask : 0);
  69}
  70
  71static inline void imx_iomuxv1_set_gius(
  72                unsigned int port, unsigned int pin, int inuse)
  73{
  74        unsigned long mask = 1 << pin;
  75
  76        imx_iomuxv1_rmwl(MXC_GIUS(port), mask, inuse ? mask : 0);
  77}
  78
  79static inline void imx_iomuxv1_set_ocr(
  80                unsigned int port, unsigned int pin, unsigned int ocr)
  81{
  82        unsigned long shift = (pin & 0xf) << 1;
  83        unsigned long mask = 3 << shift;
  84        unsigned long value = ocr << shift;
  85        unsigned long offset = pin < 16 ? MXC_OCR1(port) : MXC_OCR2(port);
  86
  87        imx_iomuxv1_rmwl(offset, mask, value);
  88}
  89
  90static inline void imx_iomuxv1_set_iconfa(
  91                unsigned int port, unsigned int pin, unsigned int aout)
  92{
  93        unsigned long shift = (pin & 0xf) << 1;
  94        unsigned long mask = 3 << shift;
  95        unsigned long value = aout << shift;
  96        unsigned long offset = pin < 16 ? MXC_ICONFA1(port) : MXC_ICONFA2(port);
  97
  98        imx_iomuxv1_rmwl(offset, mask, value);
  99}
 100
 101static inline void imx_iomuxv1_set_iconfb(
 102                unsigned int port, unsigned int pin, unsigned int bout)
 103{
 104        unsigned long shift = (pin & 0xf) << 1;
 105        unsigned long mask = 3 << shift;
 106        unsigned long value = bout << shift;
 107        unsigned long offset = pin < 16 ? MXC_ICONFB1(port) : MXC_ICONFB2(port);
 108
 109        imx_iomuxv1_rmwl(offset, mask, value);
 110}
 111
 112int mxc_gpio_mode(int gpio_mode)
 113{
 114        unsigned int pin = gpio_mode & GPIO_PIN_MASK;
 115        unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
 116        unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
 117        unsigned int aout = (gpio_mode >> GPIO_AOUT_SHIFT) & 3;
 118        unsigned int bout = (gpio_mode >> GPIO_BOUT_SHIFT) & 3;
 119
 120        if (port >= imx_iomuxv1_numports)
 121                return -EINVAL;
 122
 123        /* Pullup enable */
 124        imx_iomuxv1_set_puen(port, pin, gpio_mode & GPIO_PUEN);
 125
 126        /* Data direction */
 127        imx_iomuxv1_set_ddir(port, pin, gpio_mode & GPIO_OUT);
 128
 129        /* Primary / alternate function */
 130        imx_iomuxv1_set_gpr(port, pin, gpio_mode & GPIO_AF);
 131
 132        /* use as gpio? */
 133        imx_iomuxv1_set_gius(port, pin, !(gpio_mode & (GPIO_PF | GPIO_AF)));
 134
 135        imx_iomuxv1_set_ocr(port, pin, ocr);
 136
 137        imx_iomuxv1_set_iconfa(port, pin, aout);
 138
 139        imx_iomuxv1_set_iconfb(port, pin, bout);
 140
 141        return 0;
 142}
 143
 144static int imx_iomuxv1_setup_multiple(const int *list, unsigned count)
 145{
 146        size_t i;
 147        int ret = 0;
 148
 149        for (i = 0; i < count; ++i) {
 150                ret = mxc_gpio_mode(list[i]);
 151
 152                if (ret)
 153                        return ret;
 154        }
 155
 156        return ret;
 157}
 158
 159int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
 160                const char *label)
 161{
 162        int ret;
 163
 164        ret = imx_iomuxv1_setup_multiple(pin_list, count);
 165        return ret;
 166}
 167
 168int __init imx_iomuxv1_init(void __iomem *base, int numports)
 169{
 170        imx_iomuxv1_baseaddr = base;
 171        imx_iomuxv1_numports = numports;
 172
 173        return 0;
 174}
 175