aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-omap.c
diff options
context:
space:
mode:
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);