linux/arch/arm/mach-ns9xxx/gpio-ns9360.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-ns9xxx/gpio-ns9360.c
   3 *
   4 * Copyright (C) 2006,2007 by Digi International Inc.
   5 * All rights reserved.
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License version 2 as published by
   9 * the Free Software Foundation.
  10 */
  11#include <linux/bug.h>
  12#include <linux/errno.h>
  13#include <linux/io.h>
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16
  17#include <mach/regs-bbu.h>
  18#include <mach/processor-ns9360.h>
  19
  20#include "gpio-ns9360.h"
  21
  22static inline int ns9360_valid_gpio(unsigned gpio)
  23{
  24        return gpio <= 72;
  25}
  26
  27static inline void __iomem *ns9360_gpio_get_gconfaddr(unsigned gpio)
  28{
  29        if (gpio < 56)
  30                return BBU_GCONFb1(gpio / 8);
  31        else
  32                /*
  33                 * this could be optimised away on
  34                 * ns9750 only builds, but it isn't ...
  35                 */
  36                return BBU_GCONFb2((gpio - 56) / 8);
  37}
  38
  39static inline void __iomem *ns9360_gpio_get_gctrladdr(unsigned gpio)
  40{
  41        if (gpio < 32)
  42                return BBU_GCTRL1;
  43        else if (gpio < 64)
  44                return BBU_GCTRL2;
  45        else
  46                /* this could be optimised away on ns9750 only builds */
  47                return BBU_GCTRL3;
  48}
  49
  50static inline void __iomem *ns9360_gpio_get_gstataddr(unsigned gpio)
  51{
  52        if (gpio < 32)
  53                return BBU_GSTAT1;
  54        else if (gpio < 64)
  55                return BBU_GSTAT2;
  56        else
  57                /* this could be optimised away on ns9750 only builds */
  58                return BBU_GSTAT3;
  59}
  60
  61/*
  62 * each gpio can serve for 4 different purposes [0..3].  These are called
  63 * "functions" and passed in the parameter func.  Functions 0-2 are always some
  64 * special things, function 3 is GPIO.  If func == 3 dir specifies input or
  65 * output, and with inv you can enable an inverter (independent of func).
  66 */
  67int __ns9360_gpio_configure(unsigned gpio, int dir, int inv, int func)
  68{
  69        void __iomem *conf = ns9360_gpio_get_gconfaddr(gpio);
  70        u32 confval;
  71
  72        confval = __raw_readl(conf);
  73        REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir);
  74        REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv);
  75        REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func);
  76        __raw_writel(confval, conf);
  77
  78        return 0;
  79}
  80
  81int ns9360_gpio_configure(unsigned gpio, int inv, int func)
  82{
  83        if (likely(ns9360_valid_gpio(gpio))) {
  84                if (func == 3) {
  85                        printk(KERN_WARNING "use gpio_direction_input "
  86                                        "or gpio_direction_output\n");
  87                        return -EINVAL;
  88                } else
  89                        return __ns9360_gpio_configure(gpio, 0, inv, func);
  90        } else
  91                return -EINVAL;
  92}
  93EXPORT_SYMBOL(ns9360_gpio_configure);
  94
  95int ns9360_gpio_get_value(unsigned gpio)
  96{
  97        void __iomem *stat = ns9360_gpio_get_gstataddr(gpio);
  98        int ret;
  99
 100        ret = 1 & (__raw_readl(stat) >> (gpio & 31));
 101
 102        return ret;
 103}
 104
 105void ns9360_gpio_set_value(unsigned gpio, int value)
 106{
 107        void __iomem *ctrl = ns9360_gpio_get_gctrladdr(gpio);
 108        u32 ctrlval;
 109
 110        ctrlval = __raw_readl(ctrl);
 111
 112        if (value)
 113                ctrlval |= 1 << (gpio & 31);
 114        else
 115                ctrlval &= ~(1 << (gpio & 31));
 116
 117        __raw_writel(ctrlval, ctrl);
 118}
 119