linux/arch/mips/kernel/gpio_txx9.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * A gpio chip driver for TXx9 SoCs
   4 *
   5 * Copyright (C) 2008 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
   6 */
   7
   8#include <linux/init.h>
   9#include <linux/spinlock.h>
  10#include <linux/gpio/driver.h>
  11#include <linux/errno.h>
  12#include <linux/io.h>
  13#include <asm/txx9pio.h>
  14
  15static DEFINE_SPINLOCK(txx9_gpio_lock);
  16
  17static struct txx9_pio_reg __iomem *txx9_pioptr;
  18
  19static int txx9_gpio_get(struct gpio_chip *chip, unsigned int offset)
  20{
  21        return !!(__raw_readl(&txx9_pioptr->din) & (1 << offset));
  22}
  23
  24static void txx9_gpio_set_raw(unsigned int offset, int value)
  25{
  26        u32 val;
  27        val = __raw_readl(&txx9_pioptr->dout);
  28        if (value)
  29                val |= 1 << offset;
  30        else
  31                val &= ~(1 << offset);
  32        __raw_writel(val, &txx9_pioptr->dout);
  33}
  34
  35static void txx9_gpio_set(struct gpio_chip *chip, unsigned int offset,
  36                          int value)
  37{
  38        unsigned long flags;
  39        spin_lock_irqsave(&txx9_gpio_lock, flags);
  40        txx9_gpio_set_raw(offset, value);
  41        mmiowb();
  42        spin_unlock_irqrestore(&txx9_gpio_lock, flags);
  43}
  44
  45static int txx9_gpio_dir_in(struct gpio_chip *chip, unsigned int offset)
  46{
  47        unsigned long flags;
  48        spin_lock_irqsave(&txx9_gpio_lock, flags);
  49        __raw_writel(__raw_readl(&txx9_pioptr->dir) & ~(1 << offset),
  50                     &txx9_pioptr->dir);
  51        mmiowb();
  52        spin_unlock_irqrestore(&txx9_gpio_lock, flags);
  53        return 0;
  54}
  55
  56static int txx9_gpio_dir_out(struct gpio_chip *chip, unsigned int offset,
  57                             int value)
  58{
  59        unsigned long flags;
  60        spin_lock_irqsave(&txx9_gpio_lock, flags);
  61        txx9_gpio_set_raw(offset, value);
  62        __raw_writel(__raw_readl(&txx9_pioptr->dir) | (1 << offset),
  63                     &txx9_pioptr->dir);
  64        mmiowb();
  65        spin_unlock_irqrestore(&txx9_gpio_lock, flags);
  66        return 0;
  67}
  68
  69static struct gpio_chip txx9_gpio_chip = {
  70        .get = txx9_gpio_get,
  71        .set = txx9_gpio_set,
  72        .direction_input = txx9_gpio_dir_in,
  73        .direction_output = txx9_gpio_dir_out,
  74        .label = "TXx9",
  75};
  76
  77int __init txx9_gpio_init(unsigned long baseaddr,
  78                          unsigned int base, unsigned int num)
  79{
  80        txx9_pioptr = ioremap(baseaddr, sizeof(struct txx9_pio_reg));
  81        if (!txx9_pioptr)
  82                return -ENODEV;
  83        txx9_gpio_chip.base = base;
  84        txx9_gpio_chip.ngpio = num;
  85        return gpiochip_add_data(&txx9_gpio_chip, NULL);
  86}
  87