2019-05-28 19:57:24 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2014-05-09 15:11:47 +04:00
/*
* Copyright ( C ) 2014 Free Electrons
*
* Author : Boris BREZILLON < boris . brezillon @ free - electrons . com >
*
* Allwinner PRCM ( Power / Reset / Clock Management ) driver
*/
# include <linux/mfd/core.h>
2016-09-12 17:40:53 +03:00
# include <linux/init.h>
2014-05-09 15:11:47 +04:00
# include <linux/of.h>
2016-11-25 15:34:35 +03:00
# define SUN8I_CODEC_ANALOG_BASE 0x1c0
# define SUN8I_CODEC_ANALOG_SIZE 0x4
2014-05-09 15:11:47 +04:00
struct prcm_data {
int nsubdevs ;
const struct mfd_cell * subdevs ;
} ;
static const struct resource sun6i_a31_ar100_clk_res [ ] = {
{
. start = 0x0 ,
. end = 0x3 ,
. flags = IORESOURCE_MEM ,
} ,
} ;
static const struct resource sun6i_a31_apb0_clk_res [ ] = {
{
. start = 0xc ,
. end = 0xf ,
. flags = IORESOURCE_MEM ,
} ,
} ;
static const struct resource sun6i_a31_apb0_gates_clk_res [ ] = {
{
. start = 0x28 ,
. end = 0x2b ,
. flags = IORESOURCE_MEM ,
} ,
} ;
2014-12-17 20:18:18 +03:00
static const struct resource sun6i_a31_ir_clk_res [ ] = {
{
. start = 0x54 ,
. end = 0x57 ,
. flags = IORESOURCE_MEM ,
} ,
} ;
2014-05-09 15:11:47 +04:00
static const struct resource sun6i_a31_apb0_rstc_res [ ] = {
{
. start = 0xb0 ,
. end = 0xb3 ,
. flags = IORESOURCE_MEM ,
} ,
} ;
2016-11-25 15:34:35 +03:00
static const struct resource sun8i_codec_analog_res [ ] = {
DEFINE_RES_MEM ( SUN8I_CODEC_ANALOG_BASE , SUN8I_CODEC_ANALOG_SIZE ) ,
} ;
2014-05-09 15:11:47 +04:00
static const struct mfd_cell sun6i_a31_prcm_subdevs [ ] = {
{
. name = " sun6i-a31-ar100-clk " ,
. of_compatible = " allwinner,sun6i-a31-ar100-clk " ,
. num_resources = ARRAY_SIZE ( sun6i_a31_ar100_clk_res ) ,
. resources = sun6i_a31_ar100_clk_res ,
} ,
{
. name = " sun6i-a31-apb0-clk " ,
. of_compatible = " allwinner,sun6i-a31-apb0-clk " ,
. num_resources = ARRAY_SIZE ( sun6i_a31_apb0_clk_res ) ,
. resources = sun6i_a31_apb0_clk_res ,
} ,
{
. name = " sun6i-a31-apb0-gates-clk " ,
. of_compatible = " allwinner,sun6i-a31-apb0-gates-clk " ,
. num_resources = ARRAY_SIZE ( sun6i_a31_apb0_gates_clk_res ) ,
. resources = sun6i_a31_apb0_gates_clk_res ,
} ,
2014-12-17 20:18:18 +03:00
{
. name = " sun6i-a31-ir-clk " ,
. of_compatible = " allwinner,sun4i-a10-mod0-clk " ,
. num_resources = ARRAY_SIZE ( sun6i_a31_ir_clk_res ) ,
. resources = sun6i_a31_ir_clk_res ,
} ,
2014-05-09 15:11:47 +04:00
{
. name = " sun6i-a31-apb0-clock-reset " ,
. of_compatible = " allwinner,sun6i-a31-clock-reset " ,
. num_resources = ARRAY_SIZE ( sun6i_a31_apb0_rstc_res ) ,
. resources = sun6i_a31_apb0_rstc_res ,
} ,
} ;
2014-07-09 11:54:36 +04:00
static const struct mfd_cell sun8i_a23_prcm_subdevs [ ] = {
{
. name = " sun8i-a23-apb0-clk " ,
. of_compatible = " allwinner,sun8i-a23-apb0-clk " ,
. num_resources = ARRAY_SIZE ( sun6i_a31_apb0_clk_res ) ,
. resources = sun6i_a31_apb0_clk_res ,
} ,
{
. name = " sun6i-a31-apb0-gates-clk " ,
. of_compatible = " allwinner,sun8i-a23-apb0-gates-clk " ,
. num_resources = ARRAY_SIZE ( sun6i_a31_apb0_gates_clk_res ) ,
. resources = sun6i_a31_apb0_gates_clk_res ,
} ,
{
. name = " sun6i-a31-apb0-clock-reset " ,
. of_compatible = " allwinner,sun6i-a31-clock-reset " ,
. num_resources = ARRAY_SIZE ( sun6i_a31_apb0_rstc_res ) ,
. resources = sun6i_a31_apb0_rstc_res ,
} ,
2016-11-25 15:34:35 +03:00
{
. name = " sun8i-codec-analog " ,
. of_compatible = " allwinner,sun8i-a23-codec-analog " ,
. num_resources = ARRAY_SIZE ( sun8i_codec_analog_res ) ,
. resources = sun8i_codec_analog_res ,
} ,
2014-07-09 11:54:36 +04:00
} ;
2014-05-09 15:11:47 +04:00
static const struct prcm_data sun6i_a31_prcm_data = {
. nsubdevs = ARRAY_SIZE ( sun6i_a31_prcm_subdevs ) ,
. subdevs = sun6i_a31_prcm_subdevs ,
} ;
2014-07-09 11:54:36 +04:00
static const struct prcm_data sun8i_a23_prcm_data = {
. nsubdevs = ARRAY_SIZE ( sun8i_a23_prcm_subdevs ) ,
. subdevs = sun8i_a23_prcm_subdevs ,
} ;
2014-05-09 15:11:47 +04:00
static const struct of_device_id sun6i_prcm_dt_ids [ ] = {
{
. compatible = " allwinner,sun6i-a31-prcm " ,
. data = & sun6i_a31_prcm_data ,
} ,
2014-07-09 11:54:36 +04:00
{
. compatible = " allwinner,sun8i-a23-prcm " ,
. data = & sun8i_a23_prcm_data ,
} ,
2014-05-09 15:11:47 +04:00
{ /* sentinel */ } ,
} ;
static int sun6i_prcm_probe ( struct platform_device * pdev )
{
const struct of_device_id * match ;
const struct prcm_data * data ;
struct resource * res ;
int ret ;
2019-04-16 15:24:59 +03:00
match = of_match_node ( sun6i_prcm_dt_ids , pdev - > dev . of_node ) ;
2014-05-09 15:11:47 +04:00
if ( ! match )
return - EINVAL ;
data = match - > data ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( ! res ) {
dev_err ( & pdev - > dev , " no prcm memory region provided \n " ) ;
return - ENOENT ;
}
ret = mfd_add_devices ( & pdev - > dev , 0 , data - > subdevs , data - > nsubdevs ,
res , - 1 , NULL ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " failed to add subdevices \n " ) ;
return ret ;
}
return 0 ;
}
static struct platform_driver sun6i_prcm_driver = {
. driver = {
. name = " sun6i-prcm " ,
. of_match_table = sun6i_prcm_dt_ids ,
} ,
. probe = sun6i_prcm_probe ,
} ;
2016-09-12 17:40:53 +03:00
builtin_platform_driver ( sun6i_prcm_driver ) ;