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 int 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 return 0; 45 } 46 47 static int txx9_gpio_dir_in(struct gpio_chip *chip, unsigned int offset) 48 { 49 unsigned long flags; 50 spin_lock_irqsave(&txx9_gpio_lock, flags); 51 __raw_writel(__raw_readl(&txx9_pioptr->dir) & ~(1 << offset), 52 &txx9_pioptr->dir); 53 mmiowb(); 54 spin_unlock_irqrestore(&txx9_gpio_lock, flags); 55 return 0; 56 } 57 58 static int txx9_gpio_dir_out(struct gpio_chip *chip, unsigned int offset, 59 int value) 60 { 61 unsigned long flags; 62 spin_lock_irqsave(&txx9_gpio_lock, flags); 63 txx9_gpio_set_raw(offset, value); 64 __raw_writel(__raw_readl(&txx9_pioptr->dir) | (1 << offset), 65 &txx9_pioptr->dir); 66 mmiowb(); 67 spin_unlock_irqrestore(&txx9_gpio_lock, flags); 68 return 0; 69 } 70 71 static struct gpio_chip txx9_gpio_chip = { 72 .get = txx9_gpio_get, 73 .set = txx9_gpio_set, 74 .direction_input = txx9_gpio_dir_in, 75 .direction_output = txx9_gpio_dir_out, 76 .label = "TXx9", 77 }; 78 79 int __init txx9_gpio_init(unsigned long baseaddr, 80 unsigned int base, unsigned int num) 81 { 82 txx9_pioptr = ioremap(baseaddr, sizeof(struct txx9_pio_reg)); 83 if (!txx9_pioptr) 84 return -ENODEV; 85 txx9_gpio_chip.base = base; 86 txx9_gpio_chip.ngpio = num; 87 return gpiochip_add_data(&txx9_gpio_chip, NULL); 88 } 89