ARM: tegra: Add NCT access api and sysfs interface
[linux-3.10.git] / arch / arm / mach-tegra / nct_sysfs.c
1 /*
2  * arch/arm/mach-tegra/nct_sysfs.c
3  *
4  * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <linux/init.h>
24 #include <linux/io.h>
25 #include <linux/module.h>
26 #include <linux/moduleparam.h>
27 #include <linux/slab.h>
28 #include <linux/vmalloc.h>
29 #include <linux/fcntl.h>
30 #include <linux/fs.h>
31 #include <linux/uaccess.h>
32 #include <linux/crc32.h>
33 #include <linux/kobject.h>
34 #include <linux/sysfs.h>
35
36 #include <mach/nct.h>
37 #include "board.h"
38
39 static struct kobject *nct_kobj;
40 static ssize_t nct_item_show(struct kobject *kobj,
41         struct kobj_attribute *attr, char *buf);
42
43
44 static const struct kobj_attribute serial_number_attr =
45         __ATTR(serial_number, 0444, nct_item_show, 0);
46 static const struct kobj_attribute wifi_mac_addr_attr =
47         __ATTR(wifi_mac_addr, 0444, nct_item_show, 0);
48 static const struct kobj_attribute bt_addr_attr =
49         __ATTR(bt_addr, 0444, nct_item_show, 0);
50 static const struct kobj_attribute cm_id_attr =
51         __ATTR(cm_id, 0444, nct_item_show, 0);
52 static const struct kobj_attribute lbh_id_attr =
53         __ATTR(lbh_id, 0444, nct_item_show, 0);
54
55 static const struct attribute *nct_item_attrs[] = {
56         &serial_number_attr.attr,
57         &wifi_mac_addr_attr.attr,
58         &bt_addr_attr.attr,
59         &cm_id_attr.attr,
60         &lbh_id_attr.attr,
61         NULL
62 };
63
64 static ssize_t nct_item_show(struct kobject *kobj,
65         struct kobj_attribute *attr, char *buf)
66 {
67         ssize_t rval = 0;
68         union nct_item_type item;
69         int err;
70
71         if (attr == &serial_number_attr) {
72                 err = tegra_nct_read_item(NCT_ID_SERIAL_NUMBER, &item);
73                 if (err < 0)
74                         return 0;
75                 rval = sprintf(buf, "%s\n", item.serial_number.sn);
76         } else if (attr == &wifi_mac_addr_attr) {
77                 err = tegra_nct_read_item(NCT_ID_WIFI_MAC_ADDR, &item);
78                 if (err < 0)
79                         return 0;
80                 rval = sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
81                         item.wifi_mac_addr.addr[0],
82                         item.wifi_mac_addr.addr[1],
83                         item.wifi_mac_addr.addr[2],
84                         item.wifi_mac_addr.addr[3],
85                         item.wifi_mac_addr.addr[4],
86                         item.wifi_mac_addr.addr[5]);
87         } else if (attr == &bt_addr_attr) {
88                 err = tegra_nct_read_item(NCT_ID_BT_ADDR, &item);
89                 if (err < 0)
90                         return 0;
91                 rval = sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
92                         item.bt_addr.addr[0],
93                         item.bt_addr.addr[1],
94                         item.bt_addr.addr[2],
95                         item.bt_addr.addr[3],
96                         item.bt_addr.addr[4],
97                         item.bt_addr.addr[5]);
98         } else if (attr == &cm_id_attr) {
99                 err = tegra_nct_read_item(NCT_ID_CM_ID, &item);
100                 if (err < 0)
101                         return 0;
102                 rval = sprintf(buf, "%04d\n", item.cm_id.id);
103         } else if (attr == &lbh_id_attr) {
104                 err = tegra_nct_read_item(NCT_ID_LBH_ID, &item);
105                 if (err < 0)
106                         return 0;
107                 rval = sprintf(buf, "%04d\n", item.lbh_id.id);
108         }
109
110         return rval;
111 }
112
113 static int __init tegra_nct_sysfs_init(void)
114 {
115         if (!tegra_nct_is_init()) {
116                 pr_err("tegra_nct: not initialized\n");
117                 return 0;
118         }
119
120         nct_kobj = kobject_create_and_add("tegra_nct", kernel_kobj);
121         if (!nct_kobj) {
122                 pr_err("tegra_nct: failed to create sysfs nct object\n");
123                 return 0;
124         }
125
126         if (sysfs_create_files(nct_kobj, nct_item_attrs)) {
127                 pr_err("%s: failed to create nct item sysfs files\n", __func__);
128                 kobject_del(nct_kobj);
129                 nct_kobj = 0;
130         }
131
132         return 0;
133 }
134
135 late_initcall(tegra_nct_sysfs_init);