2019-05-27 09:55:01 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2009-07-27 17:45:56 +04:00
/*
* wm831x - otp . c - - OTP for Wolfson WM831x PMICs
*
* Copyright 2009 Wolfson Microelectronics PLC .
*
* Author : Mark Brown < broonie @ opensource . wolfsonmicro . com >
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/i2c.h>
# include <linux/bcd.h>
# include <linux/delay.h>
# include <linux/mfd/core.h>
2012-07-06 00:23:21 +04:00
# include <linux/random.h>
2009-07-27 17:45:56 +04:00
# include <linux/mfd/wm831x/core.h>
# include <linux/mfd/wm831x/otp.h>
/* In bytes */
# define WM831X_UNIQUE_ID_LEN 16
/* Read the unique ID from the chip into id */
static int wm831x_unique_id_read ( struct wm831x * wm831x , char * id )
{
int i , val ;
for ( i = 0 ; i < WM831X_UNIQUE_ID_LEN / 2 ; i + + ) {
val = wm831x_reg_read ( wm831x , WM831X_UNIQUE_ID_1 + i ) ;
if ( val < 0 )
return val ;
id [ i * 2 ] = ( val > > 8 ) & 0xff ;
id [ ( i * 2 ) + 1 ] = val & 0xff ;
}
return 0 ;
}
2021-06-02 14:43:31 +03:00
static ssize_t unique_id_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
2009-07-27 17:45:56 +04:00
{
struct wm831x * wm831x = dev_get_drvdata ( dev ) ;
2015-12-06 02:39:39 +03:00
int rval ;
2009-07-27 17:45:56 +04:00
char id [ WM831X_UNIQUE_ID_LEN ] ;
rval = wm831x_unique_id_read ( wm831x , id ) ;
if ( rval < 0 )
return 0 ;
2015-12-06 02:39:39 +03:00
return sprintf ( buf , " %*phN \n " , WM831X_UNIQUE_ID_LEN , id ) ;
2009-07-27 17:45:56 +04:00
}
2021-06-02 14:43:31 +03:00
static DEVICE_ATTR_RO ( unique_id ) ;
2009-07-27 17:45:56 +04:00
int wm831x_otp_init ( struct wm831x * wm831x )
{
2012-07-06 00:23:21 +04:00
char uuid [ WM831X_UNIQUE_ID_LEN ] ;
2009-07-27 17:45:56 +04:00
int ret ;
ret = device_create_file ( wm831x - > dev , & dev_attr_unique_id ) ;
if ( ret ! = 0 )
dev_err ( wm831x - > dev , " Unique ID attribute not created: %d \n " ,
ret ) ;
2012-07-06 00:23:21 +04:00
ret = wm831x_unique_id_read ( wm831x , uuid ) ;
if ( ret = = 0 )
add_device_randomness ( uuid , sizeof ( uuid ) ) ;
else
dev_err ( wm831x - > dev , " Failed to read UUID: %d \n " , ret ) ;
2009-07-27 17:45:56 +04:00
return ret ;
}
void wm831x_otp_exit ( struct wm831x * wm831x )
{
device_remove_file ( wm831x - > dev , & dev_attr_unique_id ) ;
}