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 15 static DEFINE_SPINLOCK(txx9_gpio_lock); 16 17 static struct txx9_pio_reg __iomem *txx9_pioptr; 18 19 static int txx9_gpio_get(struct gpio_chip *chip, unsigned int offset) 20 { 21 return !!(__raw_readl(&txx9_pioptr->din) & (1 << offset)); 22 } 23 24 static 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 35 static 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 45 static 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 56 static 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 69 static 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 77 int __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