2013-10-16 20:28:14 +04:00
/*
* Samsung EXYNOS SoC series Display Port PHY driver
*
* Copyright ( C ) 2013 Samsung Electronics Co . , Ltd .
* Author : Jingoo Han < jg1 . han @ samsung . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
2014-05-29 10:30:47 +04:00
# include <linux/err.h>
2013-10-16 20:28:14 +04:00
# include <linux/io.h>
# include <linux/kernel.h>
# include <linux/module.h>
2014-09-16 09:02:06 +04:00
# include <linux/mfd/syscon.h>
# include <linux/mfd/syscon/exynos5-pmu.h>
2013-10-16 20:28:14 +04:00
# include <linux/of.h>
# include <linux/of_address.h>
# include <linux/phy/phy.h>
# include <linux/platform_device.h>
2014-09-16 09:02:06 +04:00
# include <linux/regmap.h>
2013-10-16 20:28:14 +04:00
2014-09-16 09:02:06 +04:00
struct exynos_dp_video_phy_drvdata {
u32 phy_ctrl_offset ;
} ;
2013-10-16 20:28:14 +04:00
struct exynos_dp_video_phy {
2014-09-16 09:02:06 +04:00
struct regmap * regs ;
const struct exynos_dp_video_phy_drvdata * drvdata ;
2013-10-16 20:28:14 +04:00
} ;
static int exynos_dp_video_phy_power_on ( struct phy * phy )
{
struct exynos_dp_video_phy * state = phy_get_drvdata ( phy ) ;
2014-09-16 09:02:06 +04:00
/* Disable power isolation on DP-PHY */
2015-02-27 07:34:10 +03:00
return regmap_update_bits ( state - > regs , state - > drvdata - > phy_ctrl_offset ,
EXYNOS5_PHY_ENABLE , EXYNOS5_PHY_ENABLE ) ;
2013-10-16 20:28:14 +04:00
}
static int exynos_dp_video_phy_power_off ( struct phy * phy )
{
struct exynos_dp_video_phy * state = phy_get_drvdata ( phy ) ;
2014-09-16 09:02:06 +04:00
/* Enable power isolation on DP-PHY */
2015-02-27 07:34:10 +03:00
return regmap_update_bits ( state - > regs , state - > drvdata - > phy_ctrl_offset ,
EXYNOS5_PHY_ENABLE , 0 ) ;
2013-10-16 20:28:14 +04:00
}
2015-07-15 10:33:51 +03:00
static const struct phy_ops exynos_dp_video_phy_ops = {
2013-10-16 20:28:14 +04:00
. power_on = exynos_dp_video_phy_power_on ,
. power_off = exynos_dp_video_phy_power_off ,
. owner = THIS_MODULE ,
} ;
2014-09-16 09:02:06 +04:00
static const struct exynos_dp_video_phy_drvdata exynos5250_dp_video_phy = {
. phy_ctrl_offset = EXYNOS5_DPTX_PHY_CONTROL ,
} ;
static const struct exynos_dp_video_phy_drvdata exynos5420_dp_video_phy = {
. phy_ctrl_offset = EXYNOS5420_DPTX_PHY_CONTROL ,
} ;
static const struct of_device_id exynos_dp_video_phy_of_match [ ] = {
{
. compatible = " samsung,exynos5250-dp-video-phy " ,
. data = & exynos5250_dp_video_phy ,
} , {
. compatible = " samsung,exynos5420-dp-video-phy " ,
. data = & exynos5420_dp_video_phy ,
} ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , exynos_dp_video_phy_of_match ) ;
2013-10-16 20:28:14 +04:00
static int exynos_dp_video_phy_probe ( struct platform_device * pdev )
{
struct exynos_dp_video_phy * state ;
struct device * dev = & pdev - > dev ;
2014-09-16 09:02:06 +04:00
const struct of_device_id * match ;
2013-10-16 20:28:14 +04:00
struct phy_provider * phy_provider ;
struct phy * phy ;
state = devm_kzalloc ( dev , sizeof ( * state ) , GFP_KERNEL ) ;
if ( ! state )
return - ENOMEM ;
2014-09-16 09:02:06 +04:00
state - > regs = syscon_regmap_lookup_by_phandle ( dev - > of_node ,
" samsung,pmu-syscon " ) ;
if ( IS_ERR ( state - > regs ) ) {
dev_err ( dev , " Failed to lookup PMU regmap \n " ) ;
2013-10-16 20:28:14 +04:00
return PTR_ERR ( state - > regs ) ;
2014-09-16 09:02:06 +04:00
}
match = of_match_node ( exynos_dp_video_phy_of_match , dev - > of_node ) ;
state - > drvdata = match - > data ;
2013-10-16 20:28:14 +04:00
2014-11-19 18:28:21 +03:00
phy = devm_phy_create ( dev , NULL , & exynos_dp_video_phy_ops ) ;
2013-10-16 20:28:14 +04:00
if ( IS_ERR ( phy ) ) {
dev_err ( dev , " failed to create Display Port PHY \n " ) ;
return PTR_ERR ( phy ) ;
}
phy_set_drvdata ( phy , state ) ;
2014-02-17 12:59:25 +04:00
phy_provider = devm_of_phy_provider_register ( dev , of_phy_simple_xlate ) ;
2014-05-29 10:30:47 +04:00
return PTR_ERR_OR_ZERO ( phy_provider ) ;
2013-10-16 20:28:14 +04:00
}
static struct platform_driver exynos_dp_video_phy_driver = {
. probe = exynos_dp_video_phy_probe ,
. driver = {
. name = " exynos-dp-video-phy " ,
. of_match_table = exynos_dp_video_phy_of_match ,
}
} ;
module_platform_driver ( exynos_dp_video_phy_driver ) ;
MODULE_AUTHOR ( " Jingoo Han <jg1.han@samsung.com> " ) ;
MODULE_DESCRIPTION ( " Samsung EXYNOS SoC DP PHY driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;