9
9
#include <linux/module.h>
10
10
#include <linux/of_device.h>
11
11
#include <linux/platform_device.h>
12
+ #include <linux/reset-controller.h>
12
13
#include <linux/slab.h>
13
14
14
15
#include "clk.h"
@@ -48,6 +49,99 @@ static const char * const nic_per_divplat[] = { "nic_per_divplat" };
48
49
static const char * const lpav_axi_div [] = { "lpav_axi_div" };
49
50
static const char * const lpav_bus_div [] = { "lpav_bus_div" };
50
51
52
+ struct pcc_reset_dev {
53
+ void __iomem * base ;
54
+ struct reset_controller_dev rcdev ;
55
+ const u32 * resets ;
56
+ /* Set to imx_ccm_lock to protect register access shared with clock control */
57
+ spinlock_t * lock ;
58
+ };
59
+
60
+ #define PCC_SW_RST BIT(28)
61
+ #define to_pcc_reset_dev (_rcdev ) container_of(_rcdev, struct pcc_reset_dev, rcdev)
62
+
63
+ static const u32 pcc3_resets [] = {
64
+ 0xa8 , 0xac , 0xc8 , 0xcc , 0xd0 ,
65
+ 0xd4 , 0xd8 , 0xdc , 0xe0 , 0xe4 ,
66
+ 0xe8 , 0xec , 0xf0
67
+ };
68
+
69
+ static const u32 pcc4_resets [] = {
70
+ 0x4 , 0x8 , 0xc , 0x10 , 0x14 ,
71
+ 0x18 , 0x1c , 0x20 , 0x24 , 0x34 ,
72
+ 0x38 , 0x3c , 0x40 , 0x44 , 0x48 ,
73
+ 0x4c , 0x54
74
+ };
75
+
76
+ static const u32 pcc5_resets [] = {
77
+ 0xa0 , 0xa4 , 0xa8 , 0xac , 0xb0 ,
78
+ 0xb4 , 0xbc , 0xc0 , 0xc8 , 0xcc ,
79
+ 0xd0 , 0xf0 , 0xf4 , 0xf8
80
+ };
81
+
82
+ static int imx8ulp_pcc_assert (struct reset_controller_dev * rcdev , unsigned long id )
83
+ {
84
+ struct pcc_reset_dev * pcc_reset = to_pcc_reset_dev (rcdev );
85
+ u32 offset = pcc_reset -> resets [id ];
86
+ unsigned long flags ;
87
+ u32 val ;
88
+
89
+ spin_lock_irqsave (pcc_reset -> lock , flags );
90
+
91
+ val = readl (pcc_reset -> base + offset );
92
+ val &= ~PCC_SW_RST ;
93
+ writel (val , pcc_reset -> base + offset );
94
+
95
+ spin_unlock_irqrestore (pcc_reset -> lock , flags );
96
+
97
+ return 0 ;
98
+ }
99
+
100
+ static int imx8ulp_pcc_deassert (struct reset_controller_dev * rcdev , unsigned long id )
101
+ {
102
+ struct pcc_reset_dev * pcc_reset = to_pcc_reset_dev (rcdev );
103
+ u32 offset = pcc_reset -> resets [id ];
104
+ unsigned long flags ;
105
+ u32 val ;
106
+
107
+ spin_lock_irqsave (pcc_reset -> lock , flags );
108
+
109
+ val = readl (pcc_reset -> base + offset );
110
+ val |= PCC_SW_RST ;
111
+ writel (val , pcc_reset -> base + offset );
112
+
113
+ spin_unlock_irqrestore (pcc_reset -> lock , flags );
114
+
115
+ return 0 ;
116
+ }
117
+
118
+ static const struct reset_control_ops imx8ulp_pcc_reset_ops = {
119
+ .assert = imx8ulp_pcc_assert ,
120
+ .deassert = imx8ulp_pcc_deassert ,
121
+ };
122
+
123
+ static int imx8ulp_pcc_reset_init (struct platform_device * pdev , void __iomem * base ,
124
+ const u32 * resets , unsigned int nr_resets )
125
+ {
126
+ struct device_node * np = pdev -> dev .of_node ;
127
+ struct device * dev = & pdev -> dev ;
128
+ struct pcc_reset_dev * pcc_reset ;
129
+
130
+ pcc_reset = devm_kzalloc (dev , sizeof (* pcc_reset ), GFP_KERNEL );
131
+ if (!pcc_reset )
132
+ return - ENOMEM ;
133
+
134
+ pcc_reset -> base = base ;
135
+ pcc_reset -> lock = & imx_ccm_lock ;
136
+ pcc_reset -> resets = resets ;
137
+ pcc_reset -> rcdev .owner = THIS_MODULE ;
138
+ pcc_reset -> rcdev .nr_resets = nr_resets ;
139
+ pcc_reset -> rcdev .ops = & imx8ulp_pcc_reset_ops ;
140
+ pcc_reset -> rcdev .of_node = np ;
141
+
142
+ return devm_reset_controller_register (dev , & pcc_reset -> rcdev );
143
+ }
144
+
51
145
static int imx8ulp_clk_cgc1_init (struct platform_device * pdev )
52
146
{
53
147
struct device * dev = & pdev -> dev ;
@@ -288,10 +382,13 @@ static int imx8ulp_clk_pcc3_init(struct platform_device *pdev)
288
382
imx_check_clk_hws (clks , clk_data -> num );
289
383
290
384
ret = devm_of_clk_add_hw_provider (dev , of_clk_hw_onecell_get , clk_data );
385
+ if (ret )
386
+ return ret ;
291
387
292
388
imx_register_uart_clocks (1 );
293
389
294
- return ret ;
390
+ /* register the pcc3 reset controller */
391
+ return imx8ulp_pcc_reset_init (pdev , base , pcc3_resets , ARRAY_SIZE (pcc3_resets ));
295
392
}
296
393
297
394
static int imx8ulp_clk_pcc4_init (struct platform_device * pdev )
@@ -300,6 +397,7 @@ static int imx8ulp_clk_pcc4_init(struct platform_device *pdev)
300
397
struct clk_hw_onecell_data * clk_data ;
301
398
struct clk_hw * * clks ;
302
399
void __iomem * base ;
400
+ int ret ;
303
401
304
402
clk_data = devm_kzalloc (dev , struct_size (clk_data , hws , IMX8ULP_CLK_PCC4_END ),
305
403
GFP_KERNEL );
@@ -339,7 +437,13 @@ static int imx8ulp_clk_pcc4_init(struct platform_device *pdev)
339
437
340
438
imx_check_clk_hws (clks , clk_data -> num );
341
439
342
- return devm_of_clk_add_hw_provider (dev , of_clk_hw_onecell_get , clk_data );
440
+ ret = devm_of_clk_add_hw_provider (dev , of_clk_hw_onecell_get , clk_data );
441
+ if (ret )
442
+ return ret ;
443
+
444
+ /* register the pcc4 reset controller */
445
+ return imx8ulp_pcc_reset_init (pdev , base , pcc4_resets , ARRAY_SIZE (pcc4_resets ));
446
+
343
447
}
344
448
345
449
static int imx8ulp_clk_pcc5_init (struct platform_device * pdev )
@@ -348,6 +452,7 @@ static int imx8ulp_clk_pcc5_init(struct platform_device *pdev)
348
452
struct clk_hw_onecell_data * clk_data ;
349
453
struct clk_hw * * clks ;
350
454
void __iomem * base ;
455
+ int ret ;
351
456
352
457
clk_data = devm_kzalloc (dev , struct_size (clk_data , hws , IMX8ULP_CLK_PCC5_END ),
353
458
GFP_KERNEL );
@@ -420,7 +525,12 @@ static int imx8ulp_clk_pcc5_init(struct platform_device *pdev)
420
525
421
526
imx_check_clk_hws (clks , clk_data -> num );
422
527
423
- return devm_of_clk_add_hw_provider (dev , of_clk_hw_onecell_get , clk_data );
528
+ ret = devm_of_clk_add_hw_provider (dev , of_clk_hw_onecell_get , clk_data );
529
+ if (ret )
530
+ return ret ;
531
+
532
+ /* register the pcc5 reset controller */
533
+ return imx8ulp_pcc_reset_init (pdev , base , pcc5_resets , ARRAY_SIZE (pcc5_resets ));
424
534
}
425
535
426
536
static int imx8ulp_clk_probe (struct platform_device * pdev )
0 commit comments