Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
0004  * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
0005  * Copyright (C) 2009-2010 Florian Fainelli <florian@openwrt.org>
0006  */
0007 
0008 #include <linux/init.h>
0009 #include <linux/export.h>
0010 #include <linux/gpio.h>
0011 
0012 #include <asm/mach-ar7/ar7.h>
0013 
0014 #define AR7_GPIO_MAX 32
0015 #define TITAN_GPIO_MAX 51
0016 
0017 struct ar7_gpio_chip {
0018     void __iomem        *regs;
0019     struct gpio_chip    chip;
0020 };
0021 
0022 static int ar7_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
0023 {
0024     struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
0025     void __iomem *gpio_in = gpch->regs + AR7_GPIO_INPUT;
0026 
0027     return !!(readl(gpio_in) & (1 << gpio));
0028 }
0029 
0030 static int titan_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
0031 {
0032     struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
0033     void __iomem *gpio_in0 = gpch->regs + TITAN_GPIO_INPUT_0;
0034     void __iomem *gpio_in1 = gpch->regs + TITAN_GPIO_INPUT_1;
0035 
0036     return readl(gpio >> 5 ? gpio_in1 : gpio_in0) & (1 << (gpio & 0x1f));
0037 }
0038 
0039 static void ar7_gpio_set_value(struct gpio_chip *chip,
0040                 unsigned gpio, int value)
0041 {
0042     struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
0043     void __iomem *gpio_out = gpch->regs + AR7_GPIO_OUTPUT;
0044     unsigned tmp;
0045 
0046     tmp = readl(gpio_out) & ~(1 << gpio);
0047     if (value)
0048         tmp |= 1 << gpio;
0049     writel(tmp, gpio_out);
0050 }
0051 
0052 static void titan_gpio_set_value(struct gpio_chip *chip,
0053                 unsigned gpio, int value)
0054 {
0055     struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
0056     void __iomem *gpio_out0 = gpch->regs + TITAN_GPIO_OUTPUT_0;
0057     void __iomem *gpio_out1 = gpch->regs + TITAN_GPIO_OUTPUT_1;
0058     unsigned tmp;
0059 
0060     tmp = readl(gpio >> 5 ? gpio_out1 : gpio_out0) & ~(1 << (gpio & 0x1f));
0061     if (value)
0062         tmp |= 1 << (gpio & 0x1f);
0063     writel(tmp, gpio >> 5 ? gpio_out1 : gpio_out0);
0064 }
0065 
0066 static int ar7_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
0067 {
0068     struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
0069     void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
0070 
0071     writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
0072 
0073     return 0;
0074 }
0075 
0076 static int titan_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
0077 {
0078     struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
0079     void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
0080     void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
0081 
0082     if (gpio >= TITAN_GPIO_MAX)
0083         return -EINVAL;
0084 
0085     writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) | (1 << (gpio & 0x1f)),
0086             gpio >> 5 ? gpio_dir1 : gpio_dir0);
0087     return 0;
0088 }
0089 
0090 static int ar7_gpio_direction_output(struct gpio_chip *chip,
0091                     unsigned gpio, int value)
0092 {
0093     struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
0094     void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
0095 
0096     ar7_gpio_set_value(chip, gpio, value);
0097     writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
0098 
0099     return 0;
0100 }
0101 
0102 static int titan_gpio_direction_output(struct gpio_chip *chip,
0103                     unsigned gpio, int value)
0104 {
0105     struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
0106     void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
0107     void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
0108 
0109     if (gpio >= TITAN_GPIO_MAX)
0110         return -EINVAL;
0111 
0112     titan_gpio_set_value(chip, gpio, value);
0113     writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) & ~(1 <<
0114         (gpio & 0x1f)), gpio >> 5 ? gpio_dir1 : gpio_dir0);
0115 
0116     return 0;
0117 }
0118 
0119 static struct ar7_gpio_chip ar7_gpio_chip = {
0120     .chip = {
0121         .label          = "ar7-gpio",
0122         .direction_input    = ar7_gpio_direction_input,
0123         .direction_output   = ar7_gpio_direction_output,
0124         .set            = ar7_gpio_set_value,
0125         .get            = ar7_gpio_get_value,
0126         .base           = 0,
0127         .ngpio          = AR7_GPIO_MAX,
0128     }
0129 };
0130 
0131 static struct ar7_gpio_chip titan_gpio_chip = {
0132     .chip = {
0133         .label          = "titan-gpio",
0134         .direction_input    = titan_gpio_direction_input,
0135         .direction_output   = titan_gpio_direction_output,
0136         .set            = titan_gpio_set_value,
0137         .get            = titan_gpio_get_value,
0138         .base           = 0,
0139         .ngpio          = TITAN_GPIO_MAX,
0140     }
0141 };
0142 
0143 static inline int ar7_gpio_enable_ar7(unsigned gpio)
0144 {
0145     void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
0146 
0147     writel(readl(gpio_en) | (1 << gpio), gpio_en);
0148 
0149     return 0;
0150 }
0151 
0152 static inline int ar7_gpio_enable_titan(unsigned gpio)
0153 {
0154     void __iomem *gpio_en0 = titan_gpio_chip.regs  + TITAN_GPIO_ENBL_0;
0155     void __iomem *gpio_en1 = titan_gpio_chip.regs  + TITAN_GPIO_ENBL_1;
0156 
0157     writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) | (1 << (gpio & 0x1f)),
0158         gpio >> 5 ? gpio_en1 : gpio_en0);
0159 
0160     return 0;
0161 }
0162 
0163 int ar7_gpio_enable(unsigned gpio)
0164 {
0165     return ar7_is_titan() ? ar7_gpio_enable_titan(gpio) :
0166                 ar7_gpio_enable_ar7(gpio);
0167 }
0168 EXPORT_SYMBOL(ar7_gpio_enable);
0169 
0170 static inline int ar7_gpio_disable_ar7(unsigned gpio)
0171 {
0172     void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
0173 
0174     writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
0175 
0176     return 0;
0177 }
0178 
0179 static inline int ar7_gpio_disable_titan(unsigned gpio)
0180 {
0181     void __iomem *gpio_en0 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_0;
0182     void __iomem *gpio_en1 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_1;
0183 
0184     writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) & ~(1 << (gpio & 0x1f)),
0185             gpio >> 5 ? gpio_en1 : gpio_en0);
0186 
0187     return 0;
0188 }
0189 
0190 int ar7_gpio_disable(unsigned gpio)
0191 {
0192     return ar7_is_titan() ? ar7_gpio_disable_titan(gpio) :
0193                 ar7_gpio_disable_ar7(gpio);
0194 }
0195 EXPORT_SYMBOL(ar7_gpio_disable);
0196 
0197 struct titan_gpio_cfg {
0198     u32 reg;
0199     u32 shift;
0200     u32 func;
0201 };
0202 
0203 static const struct titan_gpio_cfg titan_gpio_table[] = {
0204     /* reg, start bit, mux value */
0205     {4, 24, 1},
0206     {4, 26, 1},
0207     {4, 28, 1},
0208     {4, 30, 1},
0209     {5, 6, 1},
0210     {5, 8, 1},
0211     {5, 10, 1},
0212     {5, 12, 1},
0213     {7, 14, 3},
0214     {7, 16, 3},
0215     {7, 18, 3},
0216     {7, 20, 3},
0217     {7, 22, 3},
0218     {7, 26, 3},
0219     {7, 28, 3},
0220     {7, 30, 3},
0221     {8, 0, 3},
0222     {8, 2, 3},
0223     {8, 4, 3},
0224     {8, 10, 3},
0225     {8, 14, 3},
0226     {8, 16, 3},
0227     {8, 18, 3},
0228     {8, 20, 3},
0229     {9, 8, 3},
0230     {9, 10, 3},
0231     {9, 12, 3},
0232     {9, 14, 3},
0233     {9, 18, 3},
0234     {9, 20, 3},
0235     {9, 24, 3},
0236     {9, 26, 3},
0237     {9, 28, 3},
0238     {9, 30, 3},
0239     {10, 0, 3},
0240     {10, 2, 3},
0241     {10, 8, 3},
0242     {10, 10, 3},
0243     {10, 12, 3},
0244     {10, 14, 3},
0245     {13, 12, 3},
0246     {13, 14, 3},
0247     {13, 16, 3},
0248     {13, 18, 3},
0249     {13, 24, 3},
0250     {13, 26, 3},
0251     {13, 28, 3},
0252     {13, 30, 3},
0253     {14, 2, 3},
0254     {14, 6, 3},
0255     {14, 8, 3},
0256     {14, 12, 3}
0257 };
0258 
0259 static int titan_gpio_pinsel(unsigned gpio)
0260 {
0261     struct titan_gpio_cfg gpio_cfg;
0262     u32 mux_status, pin_sel_reg, tmp;
0263     void __iomem *pin_sel = (void __iomem *)KSEG1ADDR(AR7_REGS_PINSEL);
0264 
0265     if (gpio >= ARRAY_SIZE(titan_gpio_table))
0266         return -EINVAL;
0267 
0268     gpio_cfg = titan_gpio_table[gpio];
0269     pin_sel_reg = gpio_cfg.reg - 1;
0270 
0271     mux_status = (readl(pin_sel + pin_sel_reg) >> gpio_cfg.shift) & 0x3;
0272 
0273     /* Check the mux status */
0274     if (!((mux_status == 0) || (mux_status == gpio_cfg.func)))
0275         return 0;
0276 
0277     /* Set the pin sel value */
0278     tmp = readl(pin_sel + pin_sel_reg);
0279     tmp |= ((gpio_cfg.func & 0x3) << gpio_cfg.shift);
0280     writel(tmp, pin_sel + pin_sel_reg);
0281 
0282     return 0;
0283 }
0284 
0285 /* Perform minimal Titan GPIO configuration */
0286 static void titan_gpio_init(void)
0287 {
0288     unsigned i;
0289 
0290     for (i = 44; i < 48; i++) {
0291         titan_gpio_pinsel(i);
0292         ar7_gpio_enable_titan(i);
0293         titan_gpio_direction_input(&titan_gpio_chip.chip, i);
0294     }
0295 }
0296 
0297 int __init ar7_gpio_init(void)
0298 {
0299     int ret;
0300     struct ar7_gpio_chip *gpch;
0301     unsigned size;
0302 
0303     if (!ar7_is_titan()) {
0304         gpch = &ar7_gpio_chip;
0305         size = 0x10;
0306     } else {
0307         gpch = &titan_gpio_chip;
0308         size = 0x1f;
0309     }
0310 
0311     gpch->regs = ioremap(AR7_REGS_GPIO, size);
0312     if (!gpch->regs) {
0313         printk(KERN_ERR "%s: failed to ioremap regs\n",
0314                     gpch->chip.label);
0315         return -ENOMEM;
0316     }
0317 
0318     ret = gpiochip_add_data(&gpch->chip, gpch);
0319     if (ret) {
0320         printk(KERN_ERR "%s: failed to add gpiochip\n",
0321                     gpch->chip.label);
0322         iounmap(gpch->regs);
0323         return ret;
0324     }
0325     printk(KERN_INFO "%s: registered %d GPIOs\n",
0326                 gpch->chip.label, gpch->chip.ngpio);
0327 
0328     if (ar7_is_titan())
0329         titan_gpio_init();
0330 
0331     return ret;
0332 }