diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-st.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-st.c | 116 |
1 files changed, 114 insertions, 2 deletions
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index 51e4f3a1d249..9fb66aa796aa 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c | |||
@@ -271,12 +271,59 @@ struct st_pctl_group { | |||
271 | struct st_pinconf *pin_conf; | 271 | struct st_pinconf *pin_conf; |
272 | }; | 272 | }; |
273 | 273 | ||
274 | /* | ||
275 | * Edge triggers are not supported at hardware level, it is supported by | ||
276 | * software by exploiting the level trigger support in hardware. | ||
277 | * Software uses a virtual register (EDGE_CONF) for edge trigger configuration | ||
278 | * of each gpio pin in a GPIO bank. | ||
279 | * | ||
280 | * Each bank has a 32 bit EDGE_CONF register which is divided in to 8 parts of | ||
281 | * 4-bits. Each 4-bit space is allocated for each pin in a gpio bank. | ||
282 | * | ||
283 | * bit allocation per pin is: | ||
284 | * Bits: [0 - 3] | [4 - 7] [8 - 11] ... ... ... ... [ 28 - 31] | ||
285 | * -------------------------------------------------------- | ||
286 | * | pin-0 | pin-2 | pin-3 | ... ... ... ... | pin -7 | | ||
287 | * -------------------------------------------------------- | ||
288 | * | ||
289 | * A pin can have one of following the values in its edge configuration field. | ||
290 | * | ||
291 | * ------- ---------------------------- | ||
292 | * [0-3] - Description | ||
293 | * ------- ---------------------------- | ||
294 | * 0000 - No edge IRQ. | ||
295 | * 0001 - Falling edge IRQ. | ||
296 | * 0010 - Rising edge IRQ. | ||
297 | * 0011 - Rising and Falling edge IRQ. | ||
298 | * ------- ---------------------------- | ||
299 | */ | ||
300 | |||
301 | #define ST_IRQ_EDGE_CONF_BITS_PER_PIN 4 | ||
302 | #define ST_IRQ_EDGE_MASK 0xf | ||
303 | #define ST_IRQ_EDGE_FALLING BIT(0) | ||
304 | #define ST_IRQ_EDGE_RISING BIT(1) | ||
305 | #define ST_IRQ_EDGE_BOTH (BIT(0) | BIT(1)) | ||
306 | |||
307 | #define ST_IRQ_RISING_EDGE_CONF(pin) \ | ||
308 | (ST_IRQ_EDGE_RISING << (pin * ST_IRQ_EDGE_CONF_BITS_PER_PIN)) | ||
309 | |||
310 | #define ST_IRQ_FALLING_EDGE_CONF(pin) \ | ||
311 | (ST_IRQ_EDGE_FALLING << (pin * ST_IRQ_EDGE_CONF_BITS_PER_PIN)) | ||
312 | |||
313 | #define ST_IRQ_BOTH_EDGE_CONF(pin) \ | ||
314 | (ST_IRQ_EDGE_BOTH << (pin * ST_IRQ_EDGE_CONF_BITS_PER_PIN)) | ||
315 | |||
316 | #define ST_IRQ_EDGE_CONF(conf, pin) \ | ||
317 | (conf >> (pin * ST_IRQ_EDGE_CONF_BITS_PER_PIN) & ST_IRQ_EDGE_MASK) | ||
318 | |||
274 | struct st_gpio_bank { | 319 | struct st_gpio_bank { |
275 | struct gpio_chip gpio_chip; | 320 | struct gpio_chip gpio_chip; |
276 | struct pinctrl_gpio_range range; | 321 | struct pinctrl_gpio_range range; |
277 | void __iomem *base; | 322 | void __iomem *base; |
278 | struct st_pio_control pc; | 323 | struct st_pio_control pc; |
279 | struct irq_domain *domain; | 324 | struct irq_domain *domain; |
325 | unsigned long irq_edge_conf; | ||
326 | spinlock_t lock; | ||
280 | }; | 327 | }; |
281 | 328 | ||
282 | struct st_pinctrl { | 329 | struct st_pinctrl { |
@@ -1262,18 +1309,37 @@ static int st_gpio_irq_set_type(struct irq_data *d, unsigned type) | |||
1262 | unsigned long flags; | 1309 | unsigned long flags; |
1263 | int comp, pin = d->hwirq; | 1310 | int comp, pin = d->hwirq; |
1264 | u32 val; | 1311 | u32 val; |
1312 | u32 pin_edge_conf = 0; | ||
1265 | 1313 | ||
1266 | switch (type) { | 1314 | switch (type) { |
1267 | case IRQ_TYPE_LEVEL_HIGH: | 1315 | case IRQ_TYPE_LEVEL_HIGH: |
1268 | comp = 0; | 1316 | comp = 0; |
1269 | break; | 1317 | break; |
1318 | case IRQ_TYPE_EDGE_FALLING: | ||
1319 | comp = 0; | ||
1320 | pin_edge_conf = ST_IRQ_FALLING_EDGE_CONF(pin); | ||
1321 | break; | ||
1270 | case IRQ_TYPE_LEVEL_LOW: | 1322 | case IRQ_TYPE_LEVEL_LOW: |
1271 | comp = 1; | 1323 | comp = 1; |
1272 | break; | 1324 | break; |
1325 | case IRQ_TYPE_EDGE_RISING: | ||
1326 | comp = 1; | ||
1327 | pin_edge_conf = ST_IRQ_RISING_EDGE_CONF(pin); | ||
1328 | break; | ||
1329 | case IRQ_TYPE_EDGE_BOTH: | ||
1330 | comp = st_gpio_get(&bank->gpio_chip, pin); | ||
1331 | pin_edge_conf = ST_IRQ_BOTH_EDGE_CONF(pin); | ||
1332 | break; | ||
1273 | default: | 1333 | default: |
1274 | return -EINVAL; | 1334 | return -EINVAL; |
1275 | } | 1335 | } |
1276 | 1336 | ||
1337 | spin_lock_irqsave(&bank->lock, flags); | ||
1338 | bank->irq_edge_conf &= ~(ST_IRQ_EDGE_MASK << ( | ||
1339 | pin * ST_IRQ_EDGE_CONF_BITS_PER_PIN)); | ||
1340 | bank->irq_edge_conf |= pin_edge_conf; | ||
1341 | spin_unlock_irqrestore(&bank->lock, flags); | ||
1342 | |||
1277 | val = readl(bank->base + REG_PIO_PCOMP); | 1343 | val = readl(bank->base + REG_PIO_PCOMP); |
1278 | val &= ~BIT(pin); | 1344 | val &= ~BIT(pin); |
1279 | val |= (comp << pin); | 1345 | val |= (comp << pin); |
@@ -1282,10 +1348,39 @@ static int st_gpio_irq_set_type(struct irq_data *d, unsigned type) | |||
1282 | return 0; | 1348 | return 0; |
1283 | } | 1349 | } |
1284 | 1350 | ||
1351 | /* | ||
1352 | * As edge triggers are not supported at hardware level, it is supported by | ||
1353 | * software by exploiting the level trigger support in hardware. | ||
1354 | * | ||
1355 | * Steps for detection raising edge interrupt in software. | ||
1356 | * | ||
1357 | * Step 1: CONFIGURE pin to detect level LOW interrupts. | ||
1358 | * | ||
1359 | * Step 2: DETECT level LOW interrupt and in irqmux/gpio bank interrupt handler, | ||
1360 | * if the value of pin is low, then CONFIGURE pin for level HIGH interrupt. | ||
1361 | * IGNORE calling the actual interrupt handler for the pin at this stage. | ||
1362 | * | ||
1363 | * Step 3: DETECT level HIGH interrupt and in irqmux/gpio-bank interrupt handler | ||
1364 | * if the value of pin is HIGH, CONFIGURE pin for level LOW interrupt and then | ||
1365 | * DISPATCH the interrupt to the interrupt handler of the pin. | ||
1366 | * | ||
1367 | * step-1 ________ __________ | ||
1368 | * | | step - 3 | ||
1369 | * | | | ||
1370 | * step -2 |_____| | ||
1371 | * | ||
1372 | * falling edge is also detected int the same way. | ||
1373 | * | ||
1374 | */ | ||
1285 | static void __gpio_irq_handler(struct st_gpio_bank *bank) | 1375 | static void __gpio_irq_handler(struct st_gpio_bank *bank) |
1286 | { | 1376 | { |
1287 | unsigned long port_in, port_mask, port_comp, active_irqs; | 1377 | unsigned long port_in, port_mask, port_comp, active_irqs; |
1288 | int n; | 1378 | unsigned long bank_edge_mask, flags; |
1379 | int n, val, ecfg; | ||
1380 | |||
1381 | spin_lock_irqsave(&bank->lock, flags); | ||
1382 | bank_edge_mask = bank->irq_edge_conf; | ||
1383 | spin_unlock_irqrestore(&bank->lock, flags); | ||
1289 | 1384 | ||
1290 | for (;;) { | 1385 | for (;;) { |
1291 | port_in = readl(bank->base + REG_PIO_PIN); | 1386 | port_in = readl(bank->base + REG_PIO_PIN); |
@@ -1298,6 +1393,22 @@ static void __gpio_irq_handler(struct st_gpio_bank *bank) | |||
1298 | break; | 1393 | break; |
1299 | 1394 | ||
1300 | for_each_set_bit(n, &active_irqs, BITS_PER_LONG) { | 1395 | for_each_set_bit(n, &active_irqs, BITS_PER_LONG) { |
1396 | /* check if we are detecting fake edges ... */ | ||
1397 | ecfg = ST_IRQ_EDGE_CONF(bank_edge_mask, n); | ||
1398 | |||
1399 | if (ecfg) { | ||
1400 | /* edge detection. */ | ||
1401 | val = st_gpio_get(&bank->gpio_chip, n); | ||
1402 | |||
1403 | writel(BIT(n), | ||
1404 | val ? bank->base + REG_PIO_SET_PCOMP : | ||
1405 | bank->base + REG_PIO_CLR_PCOMP); | ||
1406 | |||
1407 | if (ecfg != ST_IRQ_EDGE_BOTH && | ||
1408 | !((ecfg & ST_IRQ_EDGE_FALLING) ^ val)) | ||
1409 | continue; | ||
1410 | } | ||
1411 | |||
1301 | generic_handle_irq(irq_find_mapping(bank->domain, n)); | 1412 | generic_handle_irq(irq_find_mapping(bank->domain, n)); |
1302 | } | 1413 | } |
1303 | } | 1414 | } |
@@ -1359,7 +1470,7 @@ static int st_gpio_irq_domain_map(struct irq_domain *h, | |||
1359 | struct st_gpio_bank *bank = h->host_data; | 1470 | struct st_gpio_bank *bank = h->host_data; |
1360 | 1471 | ||
1361 | irq_set_chip(virq, &st_gpio_irqchip); | 1472 | irq_set_chip(virq, &st_gpio_irqchip); |
1362 | irq_set_handler(virq, handle_level_irq); | 1473 | irq_set_handler(virq, handle_simple_irq); |
1363 | set_irq_flags(virq, IRQF_VALID); | 1474 | set_irq_flags(virq, IRQF_VALID); |
1364 | irq_set_chip_data(virq, bank); | 1475 | irq_set_chip_data(virq, bank); |
1365 | 1476 | ||
@@ -1392,6 +1503,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info, | |||
1392 | bank->gpio_chip.base = bank_num * ST_GPIO_PINS_PER_BANK; | 1503 | bank->gpio_chip.base = bank_num * ST_GPIO_PINS_PER_BANK; |
1393 | bank->gpio_chip.ngpio = ST_GPIO_PINS_PER_BANK; | 1504 | bank->gpio_chip.ngpio = ST_GPIO_PINS_PER_BANK; |
1394 | bank->gpio_chip.of_node = np; | 1505 | bank->gpio_chip.of_node = np; |
1506 | spin_lock_init(&bank->lock); | ||
1395 | 1507 | ||
1396 | of_property_read_string(np, "st,bank-name", &range->name); | 1508 | of_property_read_string(np, "st,bank-name", &range->name); |
1397 | bank->gpio_chip.label = range->name; | 1509 | bank->gpio_chip.label = range->name; |