aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-omap.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-16 00:35:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-16 00:35:38 -0400
commit6de4c691eab8f421e34c5250f63bf3f477d30eec (patch)
treedd3deaa163bb478b13778a712afdfccc8cf43f20 /drivers/gpio/gpio-omap.c
parentc1c2ad82c772966d3cdb9a4852329fa2cf71853a (diff)
parenta5ec96ddfd55c501d451cb310566a1170c267ecb (diff)
Merge tag 'gpio-v4.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij: "This is the bulk of GPIO changes for the v4.19 kernel cycle. I don't know if anything in particular stands out. Maybe the Aspeed coprocessor thing from Benji: Aspeed is doing baseboard management chips (BMC's) for servers etc. These Aspeed's are ARM processors that exist inside (I guess) Intel servers, and they are moving forward to using mainline Linux in those. This is one of the pieces of the puzzle to achive that. They are doing OpenBMC, it's pretty cool: https://lwn.net/Articles/683320/ Summary: Core changes: - Add a new API for explicitly naming GPIO consumers, when needed. - Don't let userspace set values on input lines. While we do not think anyone would do this crazy thing we better plug the hole before someone uses it and think it's a nifty feature. - Avoid calling chip->request() for unused GPIOs. New drivers/subdrivers: - The Mediatek MT7621 is supported which is a big win for OpenWRT and similar router distributions using this chip, as it seems every major router manufacturer on the planet has made products using this chip: https://wikidevi.com/wiki/MediaTek_MT7621 - The Tegra 194 is now supported. - The IT87 driver now supports IT8786E and IT8718F super-IO chips. - Add support for Rockchip RK3328 in the syscon GPIO driver. Driver changes: - Handle the get/set_multiple() properly on MMIO chips with inverted direction registers. We didn't have this problem until a new chip appear that has get/set registers AND inverted direction bits, OK now we handle it. - A patch series making more error codes percolate upward properly for different errors on gpiochip_lock_as_irq(). - Get/set multiple for the OMAP driver, accelerating these multiple line operations if possible. - A coprocessor interface for the Aspeed driver. Sometimes a few GPIO lines need to be grabbed by a co-processor for doing automated tasks, sometimes they are available as GPIO lines. By adding an explicit API in this driver we make it possible for the two line consumers to coexist. (This work was made available on the ib-aspeed branch, which may be appearing in other pull requests.) - Implemented .get_direction() and open drain in the SCH311x driver. - Continuing cleanup of included headers in GPIO drivers" * tag 'gpio-v4.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (80 commits) gpio: it87: Add support for IT8613 gpio: it87: add support for IT8718F Super I/O. gpiolib: Avoid calling chip->request() for unused gpios gpio: tegra: Include the right header gpio: mmio: Fix up inverted direction registers gpio: xilinx: Use the right include gpio: timberdale: Include the right header gpio: tb10x: Use the right include gpiolib: Fix of_node inconsistency gpio: vr41xx: Bail out on gpiochip_lock_as_irq() error gpio: uniphier: Bail out on gpiochip_lock_as_irq() error gpio: xgene-sb: Don't shadow error code of gpiochip_lock_as_irq() gpio: em: Don't shadow error code of gpiochip_lock_as_irq() gpio: dwapb: Don't shadow error code of gpiochip_lock_as_irq() gpio: bcm-kona: Don't shadow error code of gpiochip_lock_as_irq() gpiolib: Don't shadow error code of gpiochip_lock_as_irq() gpio: syscon: rockchip: add GRF GPIO support for rk3328 gpio: omap: Add get/set_multiple() callbacks gpio: pxa: remove set but not used variable 'gpio_offset' gpio-it87: add support for IT8786E Super I/O ...
Diffstat (limited to 'drivers/gpio/gpio-omap.c')
-rw-r--r--drivers/gpio/gpio-omap.c88
1 files changed, 86 insertions, 2 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index d1afedf4dcbf..e81008678a38 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -77,6 +77,8 @@ struct gpio_bank {
77 bool workaround_enabled; 77 bool workaround_enabled;
78 78
79 void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable); 79 void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable);
80 void (*set_dataout_multiple)(struct gpio_bank *bank,
81 unsigned long *mask, unsigned long *bits);
80 int (*get_context_loss_count)(struct device *dev); 82 int (*get_context_loss_count)(struct device *dev);
81 83
82 struct omap_gpio_reg_offs *regs; 84 struct omap_gpio_reg_offs *regs;
@@ -161,6 +163,51 @@ static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset)
161 return (readl_relaxed(reg) & (BIT(offset))) != 0; 163 return (readl_relaxed(reg) & (BIT(offset))) != 0;
162} 164}
163 165
166/* set multiple data out values using dedicate set/clear register */
167static void omap_set_gpio_dataout_reg_multiple(struct gpio_bank *bank,
168 unsigned long *mask,
169 unsigned long *bits)
170{
171 void __iomem *reg = bank->base;
172 u32 l;
173
174 l = *bits & *mask;
175 writel_relaxed(l, reg + bank->regs->set_dataout);
176 bank->context.dataout |= l;
177
178 l = ~*bits & *mask;
179 writel_relaxed(l, reg + bank->regs->clr_dataout);
180 bank->context.dataout &= ~l;
181}
182
183/* set multiple data out values using mask register */
184static void omap_set_gpio_dataout_mask_multiple(struct gpio_bank *bank,
185 unsigned long *mask,
186 unsigned long *bits)
187{
188 void __iomem *reg = bank->base + bank->regs->dataout;
189 u32 l = (readl_relaxed(reg) & ~*mask) | (*bits & *mask);
190
191 writel_relaxed(l, reg);
192 bank->context.dataout = l;
193}
194
195static unsigned long omap_get_gpio_datain_multiple(struct gpio_bank *bank,
196 unsigned long *mask)
197{
198 void __iomem *reg = bank->base + bank->regs->datain;
199
200 return readl_relaxed(reg) & *mask;
201}
202
203static unsigned long omap_get_gpio_dataout_multiple(struct gpio_bank *bank,
204 unsigned long *mask)
205{
206 void __iomem *reg = bank->base + bank->regs->dataout;
207
208 return readl_relaxed(reg) & *mask;
209}
210
164static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set) 211static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
165{ 212{
166 int l = readl_relaxed(base + reg); 213 int l = readl_relaxed(base + reg);
@@ -968,6 +1015,26 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
968 return 0; 1015 return 0;
969} 1016}
970 1017
1018static int omap_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
1019 unsigned long *bits)
1020{
1021 struct gpio_bank *bank = gpiochip_get_data(chip);
1022 void __iomem *reg = bank->base + bank->regs->direction;
1023 unsigned long in = readl_relaxed(reg), l;
1024
1025 *bits = 0;
1026
1027 l = in & *mask;
1028 if (l)
1029 *bits |= omap_get_gpio_datain_multiple(bank, &l);
1030
1031 l = ~in & *mask;
1032 if (l)
1033 *bits |= omap_get_gpio_dataout_multiple(bank, &l);
1034
1035 return 0;
1036}
1037
971static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset, 1038static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
972 unsigned debounce) 1039 unsigned debounce)
973{ 1040{
@@ -1012,6 +1079,17 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
1012 raw_spin_unlock_irqrestore(&bank->lock, flags); 1079 raw_spin_unlock_irqrestore(&bank->lock, flags);
1013} 1080}
1014 1081
1082static void omap_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask,
1083 unsigned long *bits)
1084{
1085 struct gpio_bank *bank = gpiochip_get_data(chip);
1086 unsigned long flags;
1087
1088 raw_spin_lock_irqsave(&bank->lock, flags);
1089 bank->set_dataout_multiple(bank, mask, bits);
1090 raw_spin_unlock_irqrestore(&bank->lock, flags);
1091}
1092
1015/*---------------------------------------------------------------------*/ 1093/*---------------------------------------------------------------------*/
1016 1094
1017static void omap_gpio_show_rev(struct gpio_bank *bank) 1095static void omap_gpio_show_rev(struct gpio_bank *bank)
@@ -1073,9 +1151,11 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
1073 bank->chip.get_direction = omap_gpio_get_direction; 1151 bank->chip.get_direction = omap_gpio_get_direction;
1074 bank->chip.direction_input = omap_gpio_input; 1152 bank->chip.direction_input = omap_gpio_input;
1075 bank->chip.get = omap_gpio_get; 1153 bank->chip.get = omap_gpio_get;
1154 bank->chip.get_multiple = omap_gpio_get_multiple;
1076 bank->chip.direction_output = omap_gpio_output; 1155 bank->chip.direction_output = omap_gpio_output;
1077 bank->chip.set_config = omap_gpio_set_config; 1156 bank->chip.set_config = omap_gpio_set_config;
1078 bank->chip.set = omap_gpio_set; 1157 bank->chip.set = omap_gpio_set;
1158 bank->chip.set_multiple = omap_gpio_set_multiple;
1079 if (bank->is_mpuio) { 1159 if (bank->is_mpuio) {
1080 bank->chip.label = "mpuio"; 1160 bank->chip.label = "mpuio";
1081 if (bank->regs->wkup_en) 1161 if (bank->regs->wkup_en)
@@ -1209,10 +1289,14 @@ static int omap_gpio_probe(struct platform_device *pdev)
1209 pdata->get_context_loss_count; 1289 pdata->get_context_loss_count;
1210 } 1290 }
1211 1291
1212 if (bank->regs->set_dataout && bank->regs->clr_dataout) 1292 if (bank->regs->set_dataout && bank->regs->clr_dataout) {
1213 bank->set_dataout = omap_set_gpio_dataout_reg; 1293 bank->set_dataout = omap_set_gpio_dataout_reg;
1214 else 1294 bank->set_dataout_multiple = omap_set_gpio_dataout_reg_multiple;
1295 } else {
1215 bank->set_dataout = omap_set_gpio_dataout_mask; 1296 bank->set_dataout = omap_set_gpio_dataout_mask;
1297 bank->set_dataout_multiple =
1298 omap_set_gpio_dataout_mask_multiple;
1299 }
1216 1300
1217 raw_spin_lock_init(&bank->lock); 1301 raw_spin_lock_init(&bank->lock);
1218 raw_spin_lock_init(&bank->wa_lock); 1302 raw_spin_lock_init(&bank->wa_lock);