33 * Daire McNamara,<daire.mcnamara@microchip.com>
44 * Copyright (C) 2020 Microchip Technology Inc. All rights reserved.
55 */
6+ #include <linux/auxiliary_bus.h>
67#include <linux/clk-provider.h>
78#include <linux/io.h>
89#include <linux/module.h>
910#include <linux/platform_device.h>
1011#include <linux/slab.h>
1112#include <dt-bindings/clock/microchip,mpfs-clock.h>
13+ #include <soc/microchip/mpfs.h>
1214
1315/* address offset of control registers */
1416#define REG_MSSPLL_REF_CR 0x08u
2830#define MSSPLL_FIXED_DIV 4u
2931
3032struct mpfs_clock_data {
33+ struct device * dev ;
3134 void __iomem * base ;
3235 void __iomem * msspll_base ;
3336 struct clk_hw_onecell_data hw_data ;
@@ -307,10 +310,6 @@ static int mpfs_periph_clk_enable(struct clk_hw *hw)
307310
308311 spin_lock_irqsave (& mpfs_clk_lock , flags );
309312
310- reg = readl_relaxed (base_addr + REG_SUBBLK_RESET_CR );
311- val = reg & ~(1u << periph -> shift );
312- writel_relaxed (val , base_addr + REG_SUBBLK_RESET_CR );
313-
314313 reg = readl_relaxed (base_addr + REG_SUBBLK_CLOCK_CR );
315314 val = reg | (1u << periph -> shift );
316315 writel_relaxed (val , base_addr + REG_SUBBLK_CLOCK_CR );
@@ -344,12 +343,9 @@ static int mpfs_periph_clk_is_enabled(struct clk_hw *hw)
344343 void __iomem * base_addr = periph_hw -> sys_base ;
345344 u32 reg ;
346345
347- reg = readl_relaxed (base_addr + REG_SUBBLK_RESET_CR );
348- if ((reg & (1u << periph -> shift )) == 0u ) {
349- reg = readl_relaxed (base_addr + REG_SUBBLK_CLOCK_CR );
350- if (reg & (1u << periph -> shift ))
351- return 1 ;
352- }
346+ reg = readl_relaxed (base_addr + REG_SUBBLK_CLOCK_CR );
347+ if (reg & (1u << periph -> shift ))
348+ return 1 ;
353349
354350 return 0 ;
355351}
@@ -445,6 +441,94 @@ static int mpfs_clk_register_periphs(struct device *dev, struct mpfs_periph_hw_c
445441 return 0 ;
446442}
447443
444+ /*
445+ * Peripheral clock resets
446+ */
447+
448+ #if IS_ENABLED (CONFIG_RESET_CONTROLLER )
449+
450+ u32 mpfs_reset_read (struct device * dev )
451+ {
452+ struct mpfs_clock_data * clock_data = dev_get_drvdata (dev -> parent );
453+
454+ return readl_relaxed (clock_data -> base + REG_SUBBLK_RESET_CR );
455+ }
456+ EXPORT_SYMBOL_NS_GPL (mpfs_reset_read , MCHP_CLK_MPFS );
457+
458+ void mpfs_reset_write (struct device * dev , u32 val )
459+ {
460+ struct mpfs_clock_data * clock_data = dev_get_drvdata (dev -> parent );
461+
462+ writel_relaxed (val , clock_data -> base + REG_SUBBLK_RESET_CR );
463+ }
464+ EXPORT_SYMBOL_NS_GPL (mpfs_reset_write , MCHP_CLK_MPFS );
465+
466+ static void mpfs_reset_unregister_adev (void * _adev )
467+ {
468+ struct auxiliary_device * adev = _adev ;
469+
470+ auxiliary_device_delete (adev );
471+ }
472+
473+ static void mpfs_reset_adev_release (struct device * dev )
474+ {
475+ struct auxiliary_device * adev = to_auxiliary_dev (dev );
476+
477+ auxiliary_device_uninit (adev );
478+
479+ kfree (adev );
480+ }
481+
482+ static struct auxiliary_device * mpfs_reset_adev_alloc (struct mpfs_clock_data * clk_data )
483+ {
484+ struct auxiliary_device * adev ;
485+ int ret ;
486+
487+ adev = kzalloc (sizeof (* adev ), GFP_KERNEL );
488+ if (!adev )
489+ return ERR_PTR (- ENOMEM );
490+
491+ adev -> name = "reset-mpfs" ;
492+ adev -> dev .parent = clk_data -> dev ;
493+ adev -> dev .release = mpfs_reset_adev_release ;
494+ adev -> id = 666u ;
495+
496+ ret = auxiliary_device_init (adev );
497+ if (ret ) {
498+ kfree (adev );
499+ return ERR_PTR (ret );
500+ }
501+
502+ return adev ;
503+ }
504+
505+ static int mpfs_reset_controller_register (struct mpfs_clock_data * clk_data )
506+ {
507+ struct auxiliary_device * adev ;
508+ int ret ;
509+
510+ adev = mpfs_reset_adev_alloc (clk_data );
511+ if (IS_ERR (adev ))
512+ return PTR_ERR (adev );
513+
514+ ret = auxiliary_device_add (adev );
515+ if (ret ) {
516+ auxiliary_device_uninit (adev );
517+ return ret ;
518+ }
519+
520+ return devm_add_action_or_reset (clk_data -> dev , mpfs_reset_unregister_adev , adev );
521+ }
522+
523+ #else /* !CONFIG_RESET_CONTROLLER */
524+
525+ static int mpfs_reset_controller_register (struct mpfs_clock_data * clk_data )
526+ {
527+ return 0 ;
528+ }
529+
530+ #endif /* !CONFIG_RESET_CONTROLLER */
531+
448532static int mpfs_clk_probe (struct platform_device * pdev )
449533{
450534 struct device * dev = & pdev -> dev ;
@@ -469,6 +553,8 @@ static int mpfs_clk_probe(struct platform_device *pdev)
469553 return PTR_ERR (clk_data -> msspll_base );
470554
471555 clk_data -> hw_data .num = num_clks ;
556+ clk_data -> dev = dev ;
557+ dev_set_drvdata (dev , clk_data );
472558
473559 ret = mpfs_clk_register_mssplls (dev , mpfs_msspll_clks , ARRAY_SIZE (mpfs_msspll_clks ),
474560 clk_data );
@@ -488,14 +574,14 @@ static int mpfs_clk_probe(struct platform_device *pdev)
488574 if (ret )
489575 return ret ;
490576
491- return ret ;
577+ return mpfs_reset_controller_register ( clk_data ) ;
492578}
493579
494580static const struct of_device_id mpfs_clk_of_match_table [] = {
495581 { .compatible = "microchip,mpfs-clkcfg" , },
496582 {}
497583};
498- MODULE_DEVICE_TABLE (of , mpfs_clk_match_table );
584+ MODULE_DEVICE_TABLE (of , mpfs_clk_of_match_table );
499585
500586static struct platform_driver mpfs_clk_driver = {
501587 .probe = mpfs_clk_probe ,
0 commit comments