1 /* 2 * wm831x-otp.c -- OTP for Wolfson WM831x PMICs 3 * 4 * Copyright 2009 Wolfson Microelectronics PLC. 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 */ 14 15 #include <linux/kernel.h> 16 #include <linux/module.h> 17 #include <linux/i2c.h> 18 #include <linux/bcd.h> 19 #include <linux/delay.h> 20 #include <linux/mfd/core.h> 21 22 #include <linux/mfd/wm831x/core.h> 23 #include <linux/mfd/wm831x/otp.h> 24 25 /* In bytes */ 26 #define WM831X_UNIQUE_ID_LEN 16 27 28 /* Read the unique ID from the chip into id */ 29 static int wm831x_unique_id_read(struct wm831x *wm831x, char *id) 30 { 31 int i, val; 32 33 for (i = 0; i < WM831X_UNIQUE_ID_LEN / 2; i++) { 34 val = wm831x_reg_read(wm831x, WM831X_UNIQUE_ID_1 + i); 35 if (val < 0) 36 return val; 37 38 id[i * 2] = (val >> 8) & 0xff; 39 id[(i * 2) + 1] = val & 0xff; 40 } 41 42 return 0; 43 } 44 45 static ssize_t wm831x_unique_id_show(struct device *dev, 46 struct device_attribute *attr, char *buf) 47 { 48 struct wm831x *wm831x = dev_get_drvdata(dev); 49 int i, rval; 50 char id[WM831X_UNIQUE_ID_LEN]; 51 ssize_t ret = 0; 52 53 rval = wm831x_unique_id_read(wm831x, id); 54 if (rval < 0) 55 return 0; 56 57 for (i = 0; i < WM831X_UNIQUE_ID_LEN; i++) 58 ret += sprintf(&buf[ret], "%02x", buf[i]); 59 60 ret += sprintf(&buf[ret], "\n"); 61 62 return ret; 63 } 64 65 static DEVICE_ATTR(unique_id, 0444, wm831x_unique_id_show, NULL); 66 67 int wm831x_otp_init(struct wm831x *wm831x) 68 { 69 int ret; 70 71 ret = device_create_file(wm831x->dev, &dev_attr_unique_id); 72 if (ret != 0) 73 dev_err(wm831x->dev, "Unique ID attribute not created: %d\n", 74 ret); 75 76 return ret; 77 } 78 79 void wm831x_otp_exit(struct wm831x *wm831x) 80 { 81 device_remove_file(wm831x->dev, &dev_attr_unique_id); 82 } 83 84