2019-05-29 17:18:09 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2016-08-27 16:43:46 +03:00
/*
2017-10-09 16:26:40 +03:00
* Amlogic Meson GX eFuse Driver
2016-08-27 16:43:46 +03:00
*
* Copyright ( c ) 2016 Endless Computers , Inc .
* Author : Carlo Caione < carlo @ endlessm . com >
*/
2018-11-30 14:53:23 +03:00
# include <linux/clk.h>
2016-08-27 16:43:46 +03:00
# include <linux/module.h>
# include <linux/nvmem-provider.h>
# include <linux/of.h>
# include <linux/platform_device.h>
# include <linux/firmware/meson/meson_sm.h>
static int meson_efuse_read ( void * context , unsigned int offset ,
void * val , size_t bytes )
{
2019-07-31 11:23:39 +03:00
struct meson_sm_firmware * fw = context ;
return meson_sm_call_read ( fw , ( u8 * ) val , bytes , SM_EFUSE_READ , offset ,
2018-05-11 14:07:00 +03:00
bytes , 0 , 0 , 0 ) ;
2016-08-27 16:43:46 +03:00
}
2018-05-11 14:07:01 +03:00
static int meson_efuse_write ( void * context , unsigned int offset ,
void * val , size_t bytes )
{
2019-07-31 11:23:39 +03:00
struct meson_sm_firmware * fw = context ;
return meson_sm_call_write ( fw , ( u8 * ) val , bytes , SM_EFUSE_WRITE , offset ,
2018-05-11 14:07:01 +03:00
bytes , 0 , 0 , 0 ) ;
}
2016-08-27 16:43:46 +03:00
static const struct of_device_id meson_efuse_match [ ] = {
{ . compatible = " amlogic,meson-gxbb-efuse " , } ,
{ /* sentinel */ } ,
} ;
MODULE_DEVICE_TABLE ( of , meson_efuse_match ) ;
static int meson_efuse_probe ( struct platform_device * pdev )
{
2018-05-11 14:06:59 +03:00
struct device * dev = & pdev - > dev ;
2019-07-31 11:23:39 +03:00
struct meson_sm_firmware * fw ;
struct device_node * sm_np ;
2016-08-27 16:43:46 +03:00
struct nvmem_device * nvmem ;
2018-05-11 14:06:59 +03:00
struct nvmem_config * econfig ;
2018-11-30 14:53:23 +03:00
struct clk * clk ;
2016-08-27 16:43:46 +03:00
unsigned int size ;
2018-11-30 14:53:23 +03:00
int ret ;
2019-07-31 11:23:39 +03:00
sm_np = of_parse_phandle ( pdev - > dev . of_node , " secure-monitor " , 0 ) ;
if ( ! sm_np ) {
dev_err ( & pdev - > dev , " no secure-monitor node \n " ) ;
return - ENODEV ;
}
fw = meson_sm_get ( sm_np ) ;
of_node_put ( sm_np ) ;
if ( ! fw )
return - EPROBE_DEFER ;
2018-11-30 14:53:23 +03:00
clk = devm_clk_get ( dev , NULL ) ;
if ( IS_ERR ( clk ) ) {
ret = PTR_ERR ( clk ) ;
if ( ret ! = - EPROBE_DEFER )
dev_err ( dev , " failed to get efuse gate " ) ;
return ret ;
}
ret = clk_prepare_enable ( clk ) ;
if ( ret ) {
dev_err ( dev , " failed to enable gate " ) ;
return ret ;
}
ret = devm_add_action_or_reset ( dev ,
( void ( * ) ( void * ) ) clk_disable_unprepare ,
clk ) ;
if ( ret ) {
dev_err ( dev , " failed to add disable callback " ) ;
return ret ;
}
2016-08-27 16:43:46 +03:00
2019-07-31 11:23:39 +03:00
if ( meson_sm_call ( fw , SM_EFUSE_USER_MAX , & size , 0 , 0 , 0 , 0 , 0 ) < 0 ) {
2018-11-30 14:53:21 +03:00
dev_err ( dev , " failed to get max user " ) ;
2016-08-27 16:43:46 +03:00
return - EINVAL ;
2018-11-30 14:53:21 +03:00
}
2016-08-27 16:43:46 +03:00
2018-05-11 14:06:59 +03:00
econfig = devm_kzalloc ( dev , sizeof ( * econfig ) , GFP_KERNEL ) ;
if ( ! econfig )
return - ENOMEM ;
econfig - > dev = dev ;
econfig - > name = dev_name ( dev ) ;
2023-10-20 13:55:41 +03:00
econfig - > add_legacy_fixed_of_cells = true ;
2018-05-11 14:06:59 +03:00
econfig - > stride = 1 ;
econfig - > word_size = 1 ;
econfig - > reg_read = meson_efuse_read ;
2018-05-11 14:07:01 +03:00
econfig - > reg_write = meson_efuse_write ;
2018-05-11 14:06:59 +03:00
econfig - > size = size ;
2019-07-31 11:23:39 +03:00
econfig - > priv = fw ;
2016-08-27 16:43:46 +03:00
2018-05-11 14:06:59 +03:00
nvmem = devm_nvmem_register ( & pdev - > dev , econfig ) ;
2016-08-27 16:43:46 +03:00
2018-03-09 17:47:05 +03:00
return PTR_ERR_OR_ZERO ( nvmem ) ;
2016-08-27 16:43:46 +03:00
}
static struct platform_driver meson_efuse_driver = {
. probe = meson_efuse_probe ,
. driver = {
. name = " meson-efuse " ,
. of_match_table = meson_efuse_match ,
} ,
} ;
module_platform_driver ( meson_efuse_driver ) ;
MODULE_AUTHOR ( " Carlo Caione <carlo@endlessm.com> " ) ;
2017-10-09 16:26:40 +03:00
MODULE_DESCRIPTION ( " Amlogic Meson GX NVMEM driver " ) ;
2016-08-27 16:43:46 +03:00
MODULE_LICENSE ( " GPL v2 " ) ;