^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2009-2010 Florian Fainelli <florian@openwrt.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/mach-ar7/ar7.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define AR7_GPIO_MAX 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define TITAN_GPIO_MAX 51
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct ar7_gpio_chip {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct gpio_chip chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static int ar7_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) void __iomem *gpio_in = gpch->regs + AR7_GPIO_INPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return !!(readl(gpio_in) & (1 << gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static int titan_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) void __iomem *gpio_in0 = gpch->regs + TITAN_GPIO_INPUT_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) void __iomem *gpio_in1 = gpch->regs + TITAN_GPIO_INPUT_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return readl(gpio >> 5 ? gpio_in1 : gpio_in0) & (1 << (gpio & 0x1f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void ar7_gpio_set_value(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned gpio, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) void __iomem *gpio_out = gpch->regs + AR7_GPIO_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) tmp = readl(gpio_out) & ~(1 << gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) tmp |= 1 << gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) writel(tmp, gpio_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static void titan_gpio_set_value(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned gpio, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) void __iomem *gpio_out0 = gpch->regs + TITAN_GPIO_OUTPUT_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void __iomem *gpio_out1 = gpch->regs + TITAN_GPIO_OUTPUT_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) tmp = readl(gpio >> 5 ? gpio_out1 : gpio_out0) & ~(1 << (gpio & 0x1f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) tmp |= 1 << (gpio & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) writel(tmp, gpio >> 5 ? gpio_out1 : gpio_out0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static int ar7_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static int titan_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (gpio >= TITAN_GPIO_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) | (1 << (gpio & 0x1f)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) gpio >> 5 ? gpio_dir1 : gpio_dir0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int ar7_gpio_direction_output(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned gpio, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ar7_gpio_set_value(chip, gpio, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int titan_gpio_direction_output(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned gpio, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (gpio >= TITAN_GPIO_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) titan_gpio_set_value(chip, gpio, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) & ~(1 <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) (gpio & 0x1f)), gpio >> 5 ? gpio_dir1 : gpio_dir0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static struct ar7_gpio_chip ar7_gpio_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .label = "ar7-gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .direction_input = ar7_gpio_direction_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .direction_output = ar7_gpio_direction_output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .set = ar7_gpio_set_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .get = ar7_gpio_get_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .base = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .ngpio = AR7_GPIO_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static struct ar7_gpio_chip titan_gpio_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .label = "titan-gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .direction_input = titan_gpio_direction_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .direction_output = titan_gpio_direction_output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .set = titan_gpio_set_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .get = titan_gpio_get_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .base = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .ngpio = TITAN_GPIO_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static inline int ar7_gpio_enable_ar7(unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) writel(readl(gpio_en) | (1 << gpio), gpio_en);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static inline int ar7_gpio_enable_titan(unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) void __iomem *gpio_en0 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) void __iomem *gpio_en1 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) | (1 << (gpio & 0x1f)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) gpio >> 5 ? gpio_en1 : gpio_en0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int ar7_gpio_enable(unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return ar7_is_titan() ? ar7_gpio_enable_titan(gpio) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ar7_gpio_enable_ar7(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) EXPORT_SYMBOL(ar7_gpio_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static inline int ar7_gpio_disable_ar7(unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static inline int ar7_gpio_disable_titan(unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) void __iomem *gpio_en0 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) void __iomem *gpio_en1 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) & ~(1 << (gpio & 0x1f)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) gpio >> 5 ? gpio_en1 : gpio_en0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) int ar7_gpio_disable(unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return ar7_is_titan() ? ar7_gpio_disable_titan(gpio) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ar7_gpio_disable_ar7(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) EXPORT_SYMBOL(ar7_gpio_disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct titan_gpio_cfg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u32 shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) u32 func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static const struct titan_gpio_cfg titan_gpio_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* reg, start bit, mux value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {4, 24, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {4, 26, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {4, 28, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {4, 30, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {5, 6, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {5, 8, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {5, 10, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {5, 12, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {7, 14, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {7, 16, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {7, 18, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {7, 20, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {7, 22, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {7, 26, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {7, 28, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {7, 30, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {8, 0, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {8, 2, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {8, 4, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {8, 10, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {8, 14, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {8, 16, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {8, 18, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {8, 20, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {9, 8, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {9, 10, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {9, 12, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {9, 14, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {9, 18, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {9, 20, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {9, 24, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {9, 26, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {9, 28, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {9, 30, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {10, 0, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {10, 2, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {10, 8, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {10, 10, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {10, 12, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {10, 14, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {13, 12, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {13, 14, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {13, 16, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {13, 18, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {13, 24, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {13, 26, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {13, 28, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {13, 30, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {14, 2, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {14, 6, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {14, 8, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {14, 12, 3}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static int titan_gpio_pinsel(unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct titan_gpio_cfg gpio_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) u32 mux_status, pin_sel_reg, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) void __iomem *pin_sel = (void __iomem *)KSEG1ADDR(AR7_REGS_PINSEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (gpio >= ARRAY_SIZE(titan_gpio_table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) gpio_cfg = titan_gpio_table[gpio];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) pin_sel_reg = gpio_cfg.reg - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) mux_status = (readl(pin_sel + pin_sel_reg) >> gpio_cfg.shift) & 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* Check the mux status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!((mux_status == 0) || (mux_status == gpio_cfg.func)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* Set the pin sel value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) tmp = readl(pin_sel + pin_sel_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) tmp |= ((gpio_cfg.func & 0x3) << gpio_cfg.shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) writel(tmp, pin_sel + pin_sel_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* Perform minimal Titan GPIO configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static void titan_gpio_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) for (i = 44; i < 48; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) titan_gpio_pinsel(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ar7_gpio_enable_titan(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) titan_gpio_direction_input(&titan_gpio_chip.chip, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int __init ar7_gpio_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct ar7_gpio_chip *gpch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) unsigned size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (!ar7_is_titan()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) gpch = &ar7_gpio_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) size = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) gpch = &titan_gpio_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) size = 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) gpch->regs = ioremap(AR7_REGS_GPIO, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (!gpch->regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) printk(KERN_ERR "%s: failed to ioremap regs\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) gpch->chip.label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ret = gpiochip_add_data(&gpch->chip, gpch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) printk(KERN_ERR "%s: failed to add gpiochip\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) gpch->chip.label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) printk(KERN_INFO "%s: registered %d GPIOs\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) gpch->chip.label, gpch->chip.ngpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (ar7_is_titan())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) titan_gpio_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }