1
1
// SPDX-License-Identifier: GPL-2.0
2
2
3
+ /*
4
+ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES
5
+ */
6
+
3
7
#include <linux/bitfield.h>
4
8
#include <linux/bitops.h>
5
9
#include <linux/device.h>
6
10
#include <linux/gpio/driver.h>
11
+ #include <linux/interrupt.h>
7
12
#include <linux/io.h>
8
13
#include <linux/ioport.h>
9
14
#include <linux/kernel.h>
43
48
#define YU_GPIO_MODE0 0x0c
44
49
#define YU_GPIO_DATASET 0x14
45
50
#define YU_GPIO_DATACLEAR 0x18
51
+ #define YU_GPIO_CAUSE_RISE_EN 0x44
52
+ #define YU_GPIO_CAUSE_FALL_EN 0x48
46
53
#define YU_GPIO_MODE1_CLEAR 0x50
47
54
#define YU_GPIO_MODE0_SET 0x54
48
55
#define YU_GPIO_MODE0_CLEAR 0x58
56
+ #define YU_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x80
57
+ #define YU_GPIO_CAUSE_OR_EVTEN0 0x94
58
+ #define YU_GPIO_CAUSE_OR_CLRCAUSE 0x98
49
59
50
60
struct mlxbf2_gpio_context_save_regs {
51
61
u32 gpio_mode0 ;
@@ -55,6 +65,7 @@ struct mlxbf2_gpio_context_save_regs {
55
65
/* BlueField-2 gpio block context structure. */
56
66
struct mlxbf2_gpio_context {
57
67
struct gpio_chip gc ;
68
+ struct irq_chip irq_chip ;
58
69
59
70
/* YU GPIO blocks address */
60
71
void __iomem * gpio_io ;
@@ -218,15 +229,114 @@ static int mlxbf2_gpio_direction_output(struct gpio_chip *chip,
218
229
return ret ;
219
230
}
220
231
232
+ static void mlxbf2_gpio_irq_enable (struct irq_data * irqd )
233
+ {
234
+ struct gpio_chip * gc = irq_data_get_irq_chip_data (irqd );
235
+ struct mlxbf2_gpio_context * gs = gpiochip_get_data (gc );
236
+ int offset = irqd_to_hwirq (irqd );
237
+ unsigned long flags ;
238
+ u32 val ;
239
+
240
+ spin_lock_irqsave (& gs -> gc .bgpio_lock , flags );
241
+ val = readl (gs -> gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE );
242
+ val |= BIT (offset );
243
+ writel (val , gs -> gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE );
244
+
245
+ val = readl (gs -> gpio_io + YU_GPIO_CAUSE_OR_EVTEN0 );
246
+ val |= BIT (offset );
247
+ writel (val , gs -> gpio_io + YU_GPIO_CAUSE_OR_EVTEN0 );
248
+ spin_unlock_irqrestore (& gs -> gc .bgpio_lock , flags );
249
+ }
250
+
251
+ static void mlxbf2_gpio_irq_disable (struct irq_data * irqd )
252
+ {
253
+ struct gpio_chip * gc = irq_data_get_irq_chip_data (irqd );
254
+ struct mlxbf2_gpio_context * gs = gpiochip_get_data (gc );
255
+ int offset = irqd_to_hwirq (irqd );
256
+ unsigned long flags ;
257
+ u32 val ;
258
+
259
+ spin_lock_irqsave (& gs -> gc .bgpio_lock , flags );
260
+ val = readl (gs -> gpio_io + YU_GPIO_CAUSE_OR_EVTEN0 );
261
+ val &= ~BIT (offset );
262
+ writel (val , gs -> gpio_io + YU_GPIO_CAUSE_OR_EVTEN0 );
263
+ spin_unlock_irqrestore (& gs -> gc .bgpio_lock , flags );
264
+ }
265
+
266
+ static irqreturn_t mlxbf2_gpio_irq_handler (int irq , void * ptr )
267
+ {
268
+ struct mlxbf2_gpio_context * gs = ptr ;
269
+ struct gpio_chip * gc = & gs -> gc ;
270
+ unsigned long pending ;
271
+ u32 level ;
272
+
273
+ pending = readl (gs -> gpio_io + YU_GPIO_CAUSE_OR_CAUSE_EVTEN0 );
274
+ writel (pending , gs -> gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE );
275
+
276
+ for_each_set_bit (level , & pending , gc -> ngpio ) {
277
+ int gpio_irq = irq_find_mapping (gc -> irq .domain , level );
278
+ generic_handle_irq (gpio_irq );
279
+ }
280
+
281
+ return IRQ_RETVAL (pending );
282
+ }
283
+
284
+ static int
285
+ mlxbf2_gpio_irq_set_type (struct irq_data * irqd , unsigned int type )
286
+ {
287
+ struct gpio_chip * gc = irq_data_get_irq_chip_data (irqd );
288
+ struct mlxbf2_gpio_context * gs = gpiochip_get_data (gc );
289
+ int offset = irqd_to_hwirq (irqd );
290
+ unsigned long flags ;
291
+ bool fall = false;
292
+ bool rise = false;
293
+ u32 val ;
294
+
295
+ switch (type & IRQ_TYPE_SENSE_MASK ) {
296
+ case IRQ_TYPE_EDGE_BOTH :
297
+ fall = true;
298
+ rise = true;
299
+ break ;
300
+ case IRQ_TYPE_EDGE_RISING :
301
+ rise = true;
302
+ break ;
303
+ case IRQ_TYPE_EDGE_FALLING :
304
+ fall = true;
305
+ break ;
306
+ default :
307
+ return - EINVAL ;
308
+ }
309
+
310
+ spin_lock_irqsave (& gs -> gc .bgpio_lock , flags );
311
+ if (fall ) {
312
+ val = readl (gs -> gpio_io + YU_GPIO_CAUSE_FALL_EN );
313
+ val |= BIT (offset );
314
+ writel (val , gs -> gpio_io + YU_GPIO_CAUSE_FALL_EN );
315
+ }
316
+
317
+ if (rise ) {
318
+ val = readl (gs -> gpio_io + YU_GPIO_CAUSE_RISE_EN );
319
+ val |= BIT (offset );
320
+ writel (val , gs -> gpio_io + YU_GPIO_CAUSE_RISE_EN );
321
+ }
322
+ spin_unlock_irqrestore (& gs -> gc .bgpio_lock , flags );
323
+
324
+ return 0 ;
325
+ }
326
+
221
327
/* BlueField-2 GPIO driver initialization routine. */
222
328
static int
223
329
mlxbf2_gpio_probe (struct platform_device * pdev )
224
330
{
225
331
struct mlxbf2_gpio_context * gs ;
226
332
struct device * dev = & pdev -> dev ;
333
+ struct gpio_irq_chip * girq ;
227
334
struct gpio_chip * gc ;
228
335
unsigned int npins ;
229
- int ret ;
336
+ const char * name ;
337
+ int ret , irq ;
338
+
339
+ name = dev_name (dev );
230
340
231
341
gs = devm_kzalloc (dev , sizeof (* gs ), GFP_KERNEL );
232
342
if (!gs )
@@ -261,6 +371,34 @@ mlxbf2_gpio_probe(struct platform_device *pdev)
261
371
gc -> ngpio = npins ;
262
372
gc -> owner = THIS_MODULE ;
263
373
374
+ irq = platform_get_irq (pdev , 0 );
375
+ if (irq >= 0 ) {
376
+ gs -> irq_chip .name = name ;
377
+ gs -> irq_chip .irq_set_type = mlxbf2_gpio_irq_set_type ;
378
+ gs -> irq_chip .irq_enable = mlxbf2_gpio_irq_enable ;
379
+ gs -> irq_chip .irq_disable = mlxbf2_gpio_irq_disable ;
380
+
381
+ girq = & gs -> gc .irq ;
382
+ girq -> chip = & gs -> irq_chip ;
383
+ girq -> handler = handle_simple_irq ;
384
+ girq -> default_type = IRQ_TYPE_NONE ;
385
+ /* This will let us handle the parent IRQ in the driver */
386
+ girq -> num_parents = 0 ;
387
+ girq -> parents = NULL ;
388
+ girq -> parent_handler = NULL ;
389
+
390
+ /*
391
+ * Directly request the irq here instead of passing
392
+ * a flow-handler because the irq is shared.
393
+ */
394
+ ret = devm_request_irq (dev , irq , mlxbf2_gpio_irq_handler ,
395
+ IRQF_SHARED , name , gs );
396
+ if (ret ) {
397
+ dev_err (dev , "failed to request IRQ" );
398
+ return ret ;
399
+ }
400
+ }
401
+
264
402
platform_set_drvdata (pdev , gs );
265
403
266
404
ret = devm_gpiochip_add_data (dev , & gs -> gc , gs );
@@ -315,5 +453,5 @@ static struct platform_driver mlxbf2_gpio_driver = {
315
453
module_platform_driver (mlxbf2_gpio_driver );
316
454
317
455
MODULE_DESCRIPTION ("Mellanox BlueField-2 GPIO Driver" );
318
- MODULE_AUTHOR ("Mellanox Technologies " );
456
+ MODULE_AUTHOR (
"Asmaa Mnebhi <[email protected] > " );
319
457
MODULE_LICENSE ("GPL v2" );
0 commit comments