19
19
#include <linux/delay.h>
20
20
#include <linux/interrupt.h>
21
21
#include <linux/io.h>
22
+ #include <linux/mfd/syscon.h>
22
23
#include <linux/module.h>
23
24
#include <linux/of.h>
24
25
#include <linux/of_device.h>
25
26
#include <linux/platform_device.h>
26
27
#include <linux/regulator/consumer.h>
28
+ #include <linux/regmap.h>
27
29
28
30
#define DRV_NAME "flexcan"
29
31
131
133
(FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE)
132
134
#define FLEXCAN_ESR_ALL_INT \
133
135
(FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \
134
- FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT)
136
+ FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT | \
137
+ FLEXCAN_ESR_WAK_INT)
135
138
136
139
/* FLEXCAN interrupt flag register (IFLAG) bits */
137
140
/* Errata ERR005829 step7: Reserve first valid MB */
189
192
#define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP BIT(5) /* Use timestamp based offloading */
190
193
#define FLEXCAN_QUIRK_BROKEN_PERR_STATE BIT(6) /* No interrupt for error passive */
191
194
#define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN BIT(7) /* default to BE register access */
195
+ #define FLEXCAN_QUIRK_SETUP_STOP_MODE BIT(8) /* Setup stop mode to support wakeup */
192
196
193
197
/* Structure of the message buffer */
194
198
struct flexcan_mb {
@@ -253,6 +257,14 @@ struct flexcan_devtype_data {
253
257
u32 quirks ; /* quirks needed for different IP cores */
254
258
};
255
259
260
+ struct flexcan_stop_mode {
261
+ struct regmap * gpr ;
262
+ u8 req_gpr ;
263
+ u8 req_bit ;
264
+ u8 ack_gpr ;
265
+ u8 ack_bit ;
266
+ };
267
+
256
268
struct flexcan_priv {
257
269
struct can_priv can ;
258
270
struct can_rx_offload offload ;
@@ -267,6 +279,7 @@ struct flexcan_priv {
267
279
struct clk * clk_per ;
268
280
const struct flexcan_devtype_data * devtype_data ;
269
281
struct regulator * reg_xceiver ;
282
+ struct flexcan_stop_mode stm ;
270
283
271
284
/* Read and Write APIs */
272
285
u32 (* read )(void __iomem * addr );
@@ -290,7 +303,8 @@ static const struct flexcan_devtype_data fsl_imx28_devtype_data = {
290
303
291
304
static const struct flexcan_devtype_data fsl_imx6q_devtype_data = {
292
305
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
293
- FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE ,
306
+ FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
307
+ FLEXCAN_QUIRK_SETUP_STOP_MODE ,
294
308
};
295
309
296
310
static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
@@ -350,6 +364,49 @@ static inline void flexcan_write_le(u32 val, void __iomem *addr)
350
364
iowrite32 (val , addr );
351
365
}
352
366
367
+ static void flexcan_enable_wakeup_irq (struct flexcan_priv * priv , bool enable )
368
+ {
369
+ struct flexcan_regs __iomem * regs = priv -> regs ;
370
+ u32 reg_mcr ;
371
+
372
+ reg_mcr = priv -> read (& regs -> mcr );
373
+
374
+ if (enable )
375
+ reg_mcr |= FLEXCAN_MCR_WAK_MSK ;
376
+ else
377
+ reg_mcr &= ~FLEXCAN_MCR_WAK_MSK ;
378
+
379
+ priv -> write (reg_mcr , & regs -> mcr );
380
+ }
381
+
382
+ static inline void flexcan_enter_stop_mode (struct flexcan_priv * priv )
383
+ {
384
+ struct flexcan_regs __iomem * regs = priv -> regs ;
385
+ u32 reg_mcr ;
386
+
387
+ reg_mcr = priv -> read (& regs -> mcr );
388
+ reg_mcr |= FLEXCAN_MCR_SLF_WAK ;
389
+ priv -> write (reg_mcr , & regs -> mcr );
390
+
391
+ /* enable stop request */
392
+ regmap_update_bits (priv -> stm .gpr , priv -> stm .req_gpr ,
393
+ 1 << priv -> stm .req_bit , 1 << priv -> stm .req_bit );
394
+ }
395
+
396
+ static inline void flexcan_exit_stop_mode (struct flexcan_priv * priv )
397
+ {
398
+ struct flexcan_regs __iomem * regs = priv -> regs ;
399
+ u32 reg_mcr ;
400
+
401
+ /* remove stop request */
402
+ regmap_update_bits (priv -> stm .gpr , priv -> stm .req_gpr ,
403
+ 1 << priv -> stm .req_bit , 0 );
404
+
405
+ reg_mcr = priv -> read (& regs -> mcr );
406
+ reg_mcr &= ~FLEXCAN_MCR_SLF_WAK ;
407
+ priv -> write (reg_mcr , & regs -> mcr );
408
+ }
409
+
353
410
static inline void flexcan_error_irq_enable (const struct flexcan_priv * priv )
354
411
{
355
412
struct flexcan_regs __iomem * regs = priv -> regs ;
@@ -1265,6 +1322,59 @@ static void unregister_flexcandev(struct net_device *dev)
1265
1322
unregister_candev (dev );
1266
1323
}
1267
1324
1325
+ static int flexcan_setup_stop_mode (struct platform_device * pdev )
1326
+ {
1327
+ struct net_device * dev = platform_get_drvdata (pdev );
1328
+ struct device_node * np = pdev -> dev .of_node ;
1329
+ struct device_node * gpr_np ;
1330
+ struct flexcan_priv * priv ;
1331
+ phandle phandle ;
1332
+ u32 out_val [5 ];
1333
+ int ret ;
1334
+
1335
+ if (!np )
1336
+ return - EINVAL ;
1337
+
1338
+ /* stop mode property format is:
1339
+ * <&gpr req_gpr req_bit ack_gpr ack_bit>.
1340
+ */
1341
+ ret = of_property_read_u32_array (np , "fsl,stop-mode" , out_val ,
1342
+ ARRAY_SIZE (out_val ));
1343
+ if (ret ) {
1344
+ dev_dbg (& pdev -> dev , "no stop-mode property\n" );
1345
+ return ret ;
1346
+ }
1347
+ phandle = * out_val ;
1348
+
1349
+ gpr_np = of_find_node_by_phandle (phandle );
1350
+ if (!gpr_np ) {
1351
+ dev_dbg (& pdev -> dev , "could not find gpr node by phandle\n" );
1352
+ return PTR_ERR (gpr_np );
1353
+ }
1354
+
1355
+ priv = netdev_priv (dev );
1356
+ priv -> stm .gpr = syscon_node_to_regmap (gpr_np );
1357
+ of_node_put (gpr_np );
1358
+ if (IS_ERR (priv -> stm .gpr )) {
1359
+ dev_dbg (& pdev -> dev , "could not find gpr regmap\n" );
1360
+ return PTR_ERR (priv -> stm .gpr );
1361
+ }
1362
+
1363
+ priv -> stm .req_gpr = out_val [1 ];
1364
+ priv -> stm .req_bit = out_val [2 ];
1365
+ priv -> stm .ack_gpr = out_val [3 ];
1366
+ priv -> stm .ack_bit = out_val [4 ];
1367
+
1368
+ dev_dbg (& pdev -> dev ,
1369
+ "gpr %s req_gpr=0x02%x req_bit=%u ack_gpr=0x02%x ack_bit=%u\n" ,
1370
+ gpr_np -> full_name , priv -> stm .req_gpr , priv -> stm .req_bit ,
1371
+ priv -> stm .ack_gpr , priv -> stm .ack_bit );
1372
+
1373
+ device_set_wakeup_capable (& pdev -> dev , true);
1374
+
1375
+ return 0 ;
1376
+ }
1377
+
1268
1378
static const struct of_device_id flexcan_of_match [] = {
1269
1379
{ .compatible = "fsl,imx6q-flexcan" , .data = & fsl_imx6q_devtype_data , },
1270
1380
{ .compatible = "fsl,imx28-flexcan" , .data = & fsl_imx28_devtype_data , },
@@ -1413,6 +1523,12 @@ static int flexcan_probe(struct platform_device *pdev)
1413
1523
1414
1524
devm_can_led_init (dev );
1415
1525
1526
+ if (priv -> devtype_data -> quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE ) {
1527
+ err = flexcan_setup_stop_mode (pdev );
1528
+ if (err )
1529
+ dev_dbg (& pdev -> dev , "failed to setup stop-mode\n" );
1530
+ }
1531
+
1416
1532
dev_info (& pdev -> dev , "device registered (reg_base=%p, irq=%d)\n" ,
1417
1533
priv -> regs , dev -> irq );
1418
1534
@@ -1443,9 +1559,17 @@ static int __maybe_unused flexcan_suspend(struct device *device)
1443
1559
int err ;
1444
1560
1445
1561
if (netif_running (dev )) {
1446
- err = flexcan_chip_disable (priv );
1447
- if (err )
1448
- return err ;
1562
+ /* if wakeup is enabled, enter stop mode
1563
+ * else enter disabled mode.
1564
+ */
1565
+ if (device_may_wakeup (device )) {
1566
+ enable_irq_wake (dev -> irq );
1567
+ flexcan_enter_stop_mode (priv );
1568
+ } else {
1569
+ err = flexcan_chip_disable (priv );
1570
+ if (err )
1571
+ return err ;
1572
+ }
1449
1573
netif_stop_queue (dev );
1450
1574
netif_device_detach (dev );
1451
1575
}
@@ -1464,14 +1588,45 @@ static int __maybe_unused flexcan_resume(struct device *device)
1464
1588
if (netif_running (dev )) {
1465
1589
netif_device_attach (dev );
1466
1590
netif_start_queue (dev );
1467
- err = flexcan_chip_enable (priv );
1468
- if (err )
1469
- return err ;
1591
+ if (device_may_wakeup (device )) {
1592
+ disable_irq_wake (dev -> irq );
1593
+ } else {
1594
+ err = flexcan_chip_enable (priv );
1595
+ if (err )
1596
+ return err ;
1597
+ }
1470
1598
}
1471
1599
return 0 ;
1472
1600
}
1473
1601
1474
- static SIMPLE_DEV_PM_OPS (flexcan_pm_ops , flexcan_suspend , flexcan_resume ) ;
1602
+ static int __maybe_unused flexcan_noirq_suspend (struct device * device )
1603
+ {
1604
+ struct net_device * dev = dev_get_drvdata (device );
1605
+ struct flexcan_priv * priv = netdev_priv (dev );
1606
+
1607
+ if (netif_running (dev ) && device_may_wakeup (device ))
1608
+ flexcan_enable_wakeup_irq (priv , true);
1609
+
1610
+ return 0 ;
1611
+ }
1612
+
1613
+ static int __maybe_unused flexcan_noirq_resume (struct device * device )
1614
+ {
1615
+ struct net_device * dev = dev_get_drvdata (device );
1616
+ struct flexcan_priv * priv = netdev_priv (dev );
1617
+
1618
+ if (netif_running (dev ) && device_may_wakeup (device )) {
1619
+ flexcan_enable_wakeup_irq (priv , false);
1620
+ flexcan_exit_stop_mode (priv );
1621
+ }
1622
+
1623
+ return 0 ;
1624
+ }
1625
+
1626
+ static const struct dev_pm_ops flexcan_pm_ops = {
1627
+ SET_SYSTEM_SLEEP_PM_OPS (flexcan_suspend , flexcan_resume )
1628
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS (flexcan_noirq_suspend , flexcan_noirq_resume )
1629
+ };
1475
1630
1476
1631
static struct platform_driver flexcan_driver = {
1477
1632
.driver = {
0 commit comments