1
1
// SPDX-License-Identifier: GPL-2.0
2
2
// Copyright (c) 2019 Nuvoton Technology corporation.
3
3
4
+ #include <linux/auxiliary_bus.h>
4
5
#include <linux/delay.h>
5
6
#include <linux/err.h>
6
7
#include <linux/io.h>
10
11
#include <linux/property.h>
11
12
#include <linux/reboot.h>
12
13
#include <linux/reset-controller.h>
14
+ #include <linux/slab.h>
13
15
#include <linux/spinlock.h>
14
16
#include <linux/mfd/syscon.h>
15
17
#include <linux/regmap.h>
16
18
#include <linux/of_address.h>
17
19
20
+ #include <soc/nuvoton/clock-npcm8xx.h>
21
+
18
22
/* NPCM7xx GCR registers */
19
23
#define NPCM_MDLR_OFFSET 0x7C
20
24
#define NPCM7XX_MDLR_USBD0 BIT(9)
@@ -89,6 +93,7 @@ struct npcm_rc_data {
89
93
const struct npcm_reset_info * info ;
90
94
struct regmap * gcr_regmap ;
91
95
u32 sw_reset_number ;
96
+ struct device * dev ;
92
97
void __iomem * base ;
93
98
spinlock_t lock ;
94
99
};
@@ -372,6 +377,67 @@ static const struct reset_control_ops npcm_rc_ops = {
372
377
.status = npcm_rc_status ,
373
378
};
374
379
380
+ static void npcm_clock_unregister_adev (void * _adev )
381
+ {
382
+ struct auxiliary_device * adev = _adev ;
383
+
384
+ auxiliary_device_delete (adev );
385
+ auxiliary_device_uninit (adev );
386
+ }
387
+
388
+ static void npcm_clock_adev_release (struct device * dev )
389
+ {
390
+ struct auxiliary_device * adev = to_auxiliary_dev (dev );
391
+ struct npcm_clock_adev * rdev = to_npcm_clock_adev (adev );
392
+
393
+ kfree (rdev );
394
+ }
395
+
396
+ static struct auxiliary_device * npcm_clock_adev_alloc (struct npcm_rc_data * rst_data , char * clk_name )
397
+ {
398
+ struct npcm_clock_adev * rdev ;
399
+ struct auxiliary_device * adev ;
400
+ int ret ;
401
+
402
+ rdev = kzalloc (sizeof (* rdev ), GFP_KERNEL );
403
+ if (!rdev )
404
+ return ERR_PTR (- ENOMEM );
405
+
406
+ rdev -> base = rst_data -> base ;
407
+
408
+ adev = & rdev -> adev ;
409
+ adev -> name = clk_name ;
410
+ adev -> dev .parent = rst_data -> dev ;
411
+ adev -> dev .release = npcm_clock_adev_release ;
412
+ adev -> id = 555u ;
413
+
414
+ ret = auxiliary_device_init (adev );
415
+ if (ret ) {
416
+ kfree (rdev );
417
+ return ERR_PTR (ret );
418
+ }
419
+
420
+ return adev ;
421
+ }
422
+
423
+ static int npcm8xx_clock_controller_register (struct npcm_rc_data * rst_data , char * clk_name )
424
+ {
425
+ struct auxiliary_device * adev ;
426
+ int ret ;
427
+
428
+ adev = npcm_clock_adev_alloc (rst_data , clk_name );
429
+ if (IS_ERR (adev ))
430
+ return PTR_ERR (adev );
431
+
432
+ ret = auxiliary_device_add (adev );
433
+ if (ret ) {
434
+ auxiliary_device_uninit (adev );
435
+ return ret ;
436
+ }
437
+
438
+ return devm_add_action_or_reset (rst_data -> dev , npcm_clock_unregister_adev , adev );
439
+ }
440
+
375
441
static int npcm_rc_probe (struct platform_device * pdev )
376
442
{
377
443
struct npcm_rc_data * rc ;
@@ -392,6 +458,7 @@ static int npcm_rc_probe(struct platform_device *pdev)
392
458
rc -> rcdev .of_node = pdev -> dev .of_node ;
393
459
rc -> rcdev .of_reset_n_cells = 2 ;
394
460
rc -> rcdev .of_xlate = npcm_reset_xlate ;
461
+ rc -> dev = & pdev -> dev ;
395
462
396
463
ret = devm_reset_controller_register (& pdev -> dev , & rc -> rcdev );
397
464
if (ret ) {
@@ -408,12 +475,19 @@ static int npcm_rc_probe(struct platform_device *pdev)
408
475
rc -> restart_nb .priority = 192 ,
409
476
rc -> restart_nb .notifier_call = npcm_rc_restart ,
410
477
ret = register_restart_handler (& rc -> restart_nb );
411
- if (ret )
478
+ if (ret ) {
412
479
dev_warn (& pdev -> dev , "failed to register restart handler\n" );
480
+ return ret ;
481
+ }
413
482
}
414
483
}
415
484
416
- return ret ;
485
+ switch (rc -> info -> bmc_id ) {
486
+ case BMC_NPCM8XX :
487
+ return npcm8xx_clock_controller_register (rc , "clk-npcm8xx" );
488
+ default :
489
+ return 0 ;
490
+ }
417
491
}
418
492
419
493
static struct platform_driver npcm_rc_driver = {
0 commit comments