2018-07-10 04:14:17 +03:00
// SPDX-License-Identifier: GPL-2.0
//
2018-11-09 04:42:05 +03:00
// reset-uniphier-glue.c - Glue layer reset driver for UniPhier
2018-07-10 04:14:17 +03:00
// Copyright 2018 Socionext Inc.
// Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
# include <linux/clk.h>
# include <linux/module.h>
# include <linux/of_device.h>
# include <linux/platform_device.h>
# include <linux/reset.h>
2020-05-27 18:47:31 +03:00
# include <linux/reset/reset-simple.h>
2018-07-10 04:14:17 +03:00
# define MAX_CLKS 2
# define MAX_RSTS 2
2018-11-09 04:42:05 +03:00
struct uniphier_glue_reset_soc_data {
2018-07-10 04:14:17 +03:00
int nclks ;
const char * const * clock_names ;
int nrsts ;
const char * const * reset_names ;
} ;
2018-11-09 04:42:05 +03:00
struct uniphier_glue_reset_priv {
2018-07-10 04:14:17 +03:00
struct clk_bulk_data clk [ MAX_CLKS ] ;
2021-12-15 12:38:28 +03:00
struct reset_control_bulk_data rst [ MAX_RSTS ] ;
2018-07-10 04:14:17 +03:00
struct reset_simple_data rdata ;
2018-11-09 04:42:05 +03:00
const struct uniphier_glue_reset_soc_data * data ;
2018-07-10 04:14:17 +03:00
} ;
2021-12-15 12:38:29 +03:00
static void uniphier_clk_disable ( void * _priv )
{
struct uniphier_glue_reset_priv * priv = _priv ;
clk_bulk_disable_unprepare ( priv - > data - > nclks , priv - > clk ) ;
}
static void uniphier_rst_assert ( void * _priv )
{
struct uniphier_glue_reset_priv * priv = _priv ;
reset_control_bulk_assert ( priv - > data - > nrsts , priv - > rst ) ;
}
2018-11-09 04:42:05 +03:00
static int uniphier_glue_reset_probe ( struct platform_device * pdev )
2018-07-10 04:14:17 +03:00
{
struct device * dev = & pdev - > dev ;
2018-11-09 04:42:05 +03:00
struct uniphier_glue_reset_priv * priv ;
2018-07-10 04:14:17 +03:00
struct resource * res ;
resource_size_t size ;
2021-12-15 12:38:28 +03:00
int i , ret ;
2018-07-10 04:14:17 +03:00
priv = devm_kzalloc ( dev , sizeof ( * priv ) , GFP_KERNEL ) ;
if ( ! priv )
return - ENOMEM ;
priv - > data = of_device_get_match_data ( dev ) ;
if ( WARN_ON ( ! priv - > data | | priv - > data - > nclks > MAX_CLKS | |
priv - > data - > nrsts > MAX_RSTS ) )
return - EINVAL ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
size = resource_size ( res ) ;
priv - > rdata . membase = devm_ioremap_resource ( dev , res ) ;
if ( IS_ERR ( priv - > rdata . membase ) )
return PTR_ERR ( priv - > rdata . membase ) ;
for ( i = 0 ; i < priv - > data - > nclks ; i + + )
priv - > clk [ i ] . id = priv - > data - > clock_names [ i ] ;
ret = devm_clk_bulk_get ( dev , priv - > data - > nclks , priv - > clk ) ;
if ( ret )
return ret ;
2021-12-15 12:38:28 +03:00
for ( i = 0 ; i < priv - > data - > nrsts ; i + + )
priv - > rst [ i ] . id = priv - > data - > reset_names [ i ] ;
ret = devm_reset_control_bulk_get_shared ( dev , priv - > data - > nrsts ,
priv - > rst ) ;
if ( ret )
return ret ;
2018-07-10 04:14:17 +03:00
ret = clk_bulk_prepare_enable ( priv - > data - > nclks , priv - > clk ) ;
if ( ret )
return ret ;
2021-12-15 12:38:29 +03:00
ret = devm_add_action_or_reset ( dev , uniphier_clk_disable , priv ) ;
if ( ret )
return ret ;
2021-12-15 12:38:28 +03:00
ret = reset_control_bulk_deassert ( priv - > data - > nrsts , priv - > rst ) ;
if ( ret )
2021-12-15 12:38:29 +03:00
return ret ;
ret = devm_add_action_or_reset ( dev , uniphier_rst_assert , priv ) ;
if ( ret )
return ret ;
2018-07-10 04:14:17 +03:00
spin_lock_init ( & priv - > rdata . lock ) ;
priv - > rdata . rcdev . owner = THIS_MODULE ;
priv - > rdata . rcdev . nr_resets = size * BITS_PER_BYTE ;
priv - > rdata . rcdev . ops = & reset_simple_ops ;
priv - > rdata . rcdev . of_node = dev - > of_node ;
priv - > rdata . active_low = true ;
platform_set_drvdata ( pdev , priv ) ;
2021-12-15 12:38:29 +03:00
return devm_reset_controller_register ( dev , & priv - > rdata . rcdev ) ;
2018-07-10 04:14:17 +03:00
}
static const char * const uniphier_pro4_clock_reset_names [ ] = {
" gio " , " link " ,
} ;
2018-11-09 04:42:05 +03:00
static const struct uniphier_glue_reset_soc_data uniphier_pro4_data = {
2018-07-10 04:14:17 +03:00
. nclks = ARRAY_SIZE ( uniphier_pro4_clock_reset_names ) ,
. clock_names = uniphier_pro4_clock_reset_names ,
. nrsts = ARRAY_SIZE ( uniphier_pro4_clock_reset_names ) ,
. reset_names = uniphier_pro4_clock_reset_names ,
} ;
static const char * const uniphier_pxs2_clock_reset_names [ ] = {
" link " ,
} ;
2018-11-09 04:42:05 +03:00
static const struct uniphier_glue_reset_soc_data uniphier_pxs2_data = {
2018-07-10 04:14:17 +03:00
. nclks = ARRAY_SIZE ( uniphier_pxs2_clock_reset_names ) ,
. clock_names = uniphier_pxs2_clock_reset_names ,
. nrsts = ARRAY_SIZE ( uniphier_pxs2_clock_reset_names ) ,
. reset_names = uniphier_pxs2_clock_reset_names ,
} ;
2018-11-09 04:42:05 +03:00
static const struct of_device_id uniphier_glue_reset_match [ ] = {
2018-07-10 04:14:17 +03:00
{
. compatible = " socionext,uniphier-pro4-usb3-reset " ,
. data = & uniphier_pro4_data ,
} ,
2019-09-10 04:55:27 +03:00
{
. compatible = " socionext,uniphier-pro5-usb3-reset " ,
. data = & uniphier_pro4_data ,
} ,
2018-07-10 04:14:17 +03:00
{
. compatible = " socionext,uniphier-pxs2-usb3-reset " ,
. data = & uniphier_pxs2_data ,
} ,
{
. compatible = " socionext,uniphier-ld20-usb3-reset " ,
. data = & uniphier_pxs2_data ,
} ,
{
. compatible = " socionext,uniphier-pxs3-usb3-reset " ,
. data = & uniphier_pxs2_data ,
} ,
2021-10-05 05:10:42 +03:00
{
. compatible = " socionext,uniphier-nx1-usb3-reset " ,
. data = & uniphier_pxs2_data ,
} ,
2018-11-09 04:42:07 +03:00
{
. compatible = " socionext,uniphier-pro4-ahci-reset " ,
. data = & uniphier_pro4_data ,
} ,
{
. compatible = " socionext,uniphier-pxs2-ahci-reset " ,
. data = & uniphier_pxs2_data ,
} ,
{
. compatible = " socionext,uniphier-pxs3-ahci-reset " ,
. data = & uniphier_pxs2_data ,
} ,
2018-07-10 04:14:17 +03:00
{ /* Sentinel */ }
} ;
2018-11-09 04:42:05 +03:00
MODULE_DEVICE_TABLE ( of , uniphier_glue_reset_match ) ;
2018-07-10 04:14:17 +03:00
2018-11-09 04:42:05 +03:00
static struct platform_driver uniphier_glue_reset_driver = {
. probe = uniphier_glue_reset_probe ,
2018-07-10 04:14:17 +03:00
. driver = {
2018-11-09 04:42:05 +03:00
. name = " uniphier-glue-reset " ,
. of_match_table = uniphier_glue_reset_match ,
2018-07-10 04:14:17 +03:00
} ,
} ;
2018-11-09 04:42:05 +03:00
module_platform_driver ( uniphier_glue_reset_driver ) ;
2018-07-10 04:14:17 +03:00
MODULE_AUTHOR ( " Kunihiko Hayashi <hayashi.kunihiko@socionext.com> " ) ;
2018-11-09 04:42:05 +03:00
MODULE_DESCRIPTION ( " UniPhier Glue layer reset driver " ) ;
2018-07-10 04:14:17 +03:00
MODULE_LICENSE ( " GPL " ) ;