2019-05-28 09:57:21 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2012-11-22 11:35:39 +01:00
/*
* abx500 clock implementation for ux500 platform .
*
* Copyright ( C ) 2012 ST - Ericsson SA
* Author : Ulf Hansson < ulf . hansson @ linaro . org >
*/
# include <linux/err.h>
# include <linux/module.h>
# include <linux/device.h>
2017-01-13 16:08:42 +01:00
# include <linux/of.h>
2012-11-22 11:35:39 +01:00
# include <linux/platform_device.h>
# include <linux/mfd/abx500/ab8500.h>
2013-04-03 01:06:26 +02:00
# include <linux/mfd/abx500/ab8500-sysctrl.h>
# include <linux/clkdev.h>
# include <linux/clk-provider.h>
2017-01-13 16:08:42 +01:00
# include <dt-bindings/clock/ste-ab8500.h>
2013-04-03 01:06:26 +02:00
# include "clk.h"
2012-11-22 11:35:39 +01:00
2017-01-13 16:08:42 +01:00
# define AB8500_NUM_CLKS 6
static struct clk * ab8500_clks [ AB8500_NUM_CLKS ] ;
static struct clk_onecell_data ab8500_clk_data ;
2012-11-22 11:35:39 +01:00
/* Clock definitions for ab8500 */
static int ab8500_reg_clks ( struct device * dev )
{
2013-04-03 01:06:26 +02:00
int ret ;
struct clk * clk ;
2017-01-13 16:08:42 +01:00
struct device_node * np = dev - > of_node ;
2013-04-03 01:06:26 +02:00
const char * intclk_parents [ ] = { " ab8500_sysclk " , " ulpclk " } ;
u16 intclk_reg_sel [ ] = { 0 , AB8500_SYSULPCLKCTRL1 } ;
u8 intclk_reg_mask [ ] = { 0 , AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK } ;
u8 intclk_reg_bits [ ] = {
0 ,
( 1 < < AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_SHIFT )
} ;
/* Enable SWAT */
ret = ab8500_sysctrl_set ( AB8500_SWATCTRL , AB8500_SWATCTRL_SWATENABLE ) ;
if ( ret )
return ret ;
/* ab8500_sysclk2 */
clk = clk_reg_sysctrl_gate ( dev , " ab8500_sysclk2 " , " ab8500_sysclk " ,
AB8500_SYSULPCLKCTRL1 , AB8500_SYSULPCLKCTRL1_SYSCLKBUF2REQ ,
AB8500_SYSULPCLKCTRL1_SYSCLKBUF2REQ , 0 , 0 ) ;
2017-01-13 16:08:42 +01:00
ab8500_clks [ AB8500_SYSCLK_BUF2 ] = clk ;
2013-04-03 01:06:26 +02:00
/* ab8500_sysclk3 */
clk = clk_reg_sysctrl_gate ( dev , " ab8500_sysclk3 " , " ab8500_sysclk " ,
AB8500_SYSULPCLKCTRL1 , AB8500_SYSULPCLKCTRL1_SYSCLKBUF3REQ ,
AB8500_SYSULPCLKCTRL1_SYSCLKBUF3REQ , 0 , 0 ) ;
2017-01-13 16:08:42 +01:00
ab8500_clks [ AB8500_SYSCLK_BUF3 ] = clk ;
2013-04-03 01:06:26 +02:00
/* ab8500_sysclk4 */
clk = clk_reg_sysctrl_gate ( dev , " ab8500_sysclk4 " , " ab8500_sysclk " ,
AB8500_SYSULPCLKCTRL1 , AB8500_SYSULPCLKCTRL1_SYSCLKBUF4REQ ,
AB8500_SYSULPCLKCTRL1_SYSCLKBUF4REQ , 0 , 0 ) ;
2017-01-13 16:08:42 +01:00
ab8500_clks [ AB8500_SYSCLK_BUF4 ] = clk ;
2013-04-03 01:06:26 +02:00
/* ab_ulpclk */
clk = clk_reg_sysctrl_gate_fixed_rate ( dev , " ulpclk " , NULL ,
AB8500_SYSULPCLKCTRL1 , AB8500_SYSULPCLKCTRL1_ULPCLKREQ ,
AB8500_SYSULPCLKCTRL1_ULPCLKREQ ,
2016-03-01 11:00:04 -08:00
38400000 , 9000 , 0 ) ;
2017-01-13 16:08:42 +01:00
ab8500_clks [ AB8500_SYSCLK_ULP ] = clk ;
2013-04-03 01:06:26 +02:00
/* ab8500_intclk */
clk = clk_reg_sysctrl_set_parent ( dev , " intclk " , intclk_parents , 2 ,
intclk_reg_sel , intclk_reg_mask , intclk_reg_bits , 0 ) ;
2017-01-13 16:08:42 +01:00
ab8500_clks [ AB8500_SYSCLK_INT ] = clk ;
2013-04-03 01:06:26 +02:00
/* ab8500_audioclk */
clk = clk_reg_sysctrl_gate ( dev , " audioclk " , " intclk " ,
AB8500_SYSULPCLKCTRL1 , AB8500_SYSULPCLKCTRL1_AUDIOCLKENA ,
AB8500_SYSULPCLKCTRL1_AUDIOCLKENA , 0 , 0 ) ;
2017-01-13 16:08:42 +01:00
ab8500_clks [ AB8500_SYSCLK_AUDIO ] = clk ;
ab8500_clk_data . clks = ab8500_clks ;
ab8500_clk_data . clk_num = ARRAY_SIZE ( ab8500_clks ) ;
of_clk_add_provider ( np , of_clk_src_onecell_get , & ab8500_clk_data ) ;
dev_info ( dev , " registered clocks for ab850x \n " ) ;
2013-04-03 01:06:26 +02:00
2012-11-22 11:35:39 +01:00
return 0 ;
}
2012-12-21 15:14:44 -08:00
static int abx500_clk_probe ( struct platform_device * pdev )
2012-11-22 11:35:39 +01:00
{
struct ab8500 * parent = dev_get_drvdata ( pdev - > dev . parent ) ;
int ret ;
if ( is_ab8500 ( parent ) | | is_ab8505 ( parent ) ) {
ret = ab8500_reg_clks ( & pdev - > dev ) ;
} else {
dev_err ( & pdev - > dev , " non supported plf id \n " ) ;
return - ENODEV ;
}
return ret ;
}
2017-01-13 16:08:42 +01:00
static const struct of_device_id abx500_clk_match [ ] = {
{ . compatible = " stericsson,ab8500-clk " , } ,
{ }
} ;
2012-11-22 11:35:39 +01:00
static struct platform_driver abx500_clk_driver = {
. driver = {
. name = " abx500-clk " ,
2017-01-13 16:08:42 +01:00
. of_match_table = abx500_clk_match ,
2012-11-22 11:35:39 +01:00
} ,
. probe = abx500_clk_probe ,
} ;
static int __init abx500_clk_init ( void )
{
return platform_driver_register ( & abx500_clk_driver ) ;
}
arch_initcall ( abx500_clk_init ) ;
MODULE_AUTHOR ( " Ulf Hansson <ulf.hansson@linaro.org " ) ;
MODULE_DESCRIPTION ( " ABX500 clk driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;