Blame view

drivers/mfd/wm831x-otp.c 1.97 KB
6704e5171   Mark Brown   mfd: Add basic WM...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /*
   * wm831x-otp.c  --  OTP for Wolfson WM831x PMICs
   *
   * Copyright 2009 Wolfson Microelectronics PLC.
   *
   * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   *
   *  This program is free software; you can redistribute  it and/or modify it
   *  under  the terms of  the GNU General  Public License as published by the
   *  Free Software Foundation;  either version 2 of the  License, or (at your
   *  option) any later version.
   *
   */
  
  #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>
27130f0cc   Mark Brown   mfd: wm831x: Feed...
21
  #include <linux/random.h>
6704e5171   Mark Brown   mfd: Add basic WM...
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  
  #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;
  }
  
  static ssize_t wm831x_unique_id_show(struct device *dev,
  				     struct device_attribute *attr, char *buf)
  {
  	struct wm831x *wm831x = dev_get_drvdata(dev);
a5656a708   Rasmus Villemoes   mfd: wm831x: Fix ...
50
  	int rval;
6704e5171   Mark Brown   mfd: Add basic WM...
51
  	char id[WM831X_UNIQUE_ID_LEN];
6704e5171   Mark Brown   mfd: Add basic WM...
52
53
54
55
  
  	rval = wm831x_unique_id_read(wm831x, id);
  	if (rval < 0)
  		return 0;
a5656a708   Rasmus Villemoes   mfd: wm831x: Fix ...
56
57
  	return sprintf(buf, "%*phN
  ", WM831X_UNIQUE_ID_LEN, id);
6704e5171   Mark Brown   mfd: Add basic WM...
58
59
60
61
62
63
  }
  
  static DEVICE_ATTR(unique_id, 0444, wm831x_unique_id_show, NULL);
  
  int wm831x_otp_init(struct wm831x *wm831x)
  {
27130f0cc   Mark Brown   mfd: wm831x: Feed...
64
  	char uuid[WM831X_UNIQUE_ID_LEN];
6704e5171   Mark Brown   mfd: Add basic WM...
65
66
67
68
69
70
71
  	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
  ",
  			ret);
27130f0cc   Mark Brown   mfd: wm831x: Feed...
72
73
74
75
76
77
  	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
  ", ret);
6704e5171   Mark Brown   mfd: Add basic WM...
78
79
80
81
82
83
84
  	return ret;
  }
  
  void wm831x_otp_exit(struct wm831x *wm831x)
  {
  	device_remove_file(wm831x->dev, &dev_attr_unique_id);
  }