blob: cfcbf34a2b35225996b394d9e60fa821087b6512 [file] [log] [blame]
/*
* arch/arm/mach-tegra/nct_sysfs.c
*
* Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
*
* 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.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/crc32.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <mach/nct.h>
#include "board.h"
DEFINE_MUTEX(item_lock);
static struct kobject *nct_kobj;
static union nct_item_type item;
static ssize_t nct_item_show_serial(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_SERIAL_NUMBER, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%s\n", item.serial_number.sn);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_wifi(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_WIFI_MAC_ADDR, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
item.wifi_mac_addr.addr[0],
item.wifi_mac_addr.addr[1],
item.wifi_mac_addr.addr[2],
item.wifi_mac_addr.addr[3],
item.wifi_mac_addr.addr[4],
item.wifi_mac_addr.addr[5]);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_bt(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_BT_ADDR, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
item.bt_addr.addr[0],
item.bt_addr.addr[1],
item.bt_addr.addr[2],
item.bt_addr.addr[3],
item.bt_addr.addr[4],
item.bt_addr.addr[5]);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_cm(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_CM_ID, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%04d\n", item.cm_id.id);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_lbh(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_LBH_ID, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%04d\n", item.lbh_id.id);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_boardinfo(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_BOARD_INFO, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf,
"Proc: %4u (sku: %u, fab: %u)\n"
"PMU : %4u (sku: %u, fab: %u)\n"
"Disp: %4u (sku: %u, fab: %u)\n",
item.board_info.proc_board_id,
item.board_info.proc_sku,
item.board_info.proc_fab,
item.board_info.pmu_board_id,
item.board_info.pmu_sku,
item.board_info.pmu_fab,
item.board_info.display_board_id,
item.board_info.display_sku,
item.board_info.display_fab);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_gps(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_GPS_ID, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%04d\n", item.gps_id.id);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_lcd(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_LCD_ID, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%04d\n", item.lcd_id.id);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_accelerometer(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_ACCELEROMETER_ID, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%04d\n", item.accelerometer_id.id);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_compass(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_COMPASS_ID, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%04d\n", item.compass_id.id);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_gyroscope(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_GYROSCOPE_ID, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%04d\n", item.gyroscope_id.id);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_light(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_LIGHT_ID, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%04d\n", item.light_id.id);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_charger(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_CHARGER_ID, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%04d\n", item.charger_id.id);
mutex_unlock(&item_lock);
return rval;
}
static ssize_t nct_item_show_touch(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t rval = 0;
int err;
mutex_lock(&item_lock);
err = tegra_nct_read_item(NCT_ID_TOUCH_ID, &item);
if (err < 0) {
mutex_unlock(&item_lock);
return 0;
}
rval = sprintf(buf, "%04d\n", item.touch_id.id);
mutex_unlock(&item_lock);
return rval;
}
static const struct kobj_attribute serial_number_attr =
__ATTR(serial_number, 0444, nct_item_show_serial, 0);
static const struct kobj_attribute wifi_mac_addr_attr =
__ATTR(wifi_mac_addr, 0444, nct_item_show_wifi, 0);
static const struct kobj_attribute bt_addr_attr =
__ATTR(bt_addr, 0444, nct_item_show_bt, 0);
static const struct kobj_attribute cm_id_attr =
__ATTR(cm_id, 0444, nct_item_show_cm, 0);
static const struct kobj_attribute lbh_id_attr =
__ATTR(lbh_id, 0444, nct_item_show_lbh, 0);
static const struct kobj_attribute boardinfo_id_attr =
__ATTR(boardinfo_id, 0444, nct_item_show_boardinfo, 0);
static const struct kobj_attribute gps_id_attr =
__ATTR(gps_id, 0444, nct_item_show_gps, 0);
static const struct kobj_attribute lcd_id_attr =
__ATTR(lcd_id, 0444, nct_item_show_lcd, 0);
static const struct kobj_attribute accelerometer_id_attr =
__ATTR(accelerometer_id, 0444, nct_item_show_accelerometer, 0);
static const struct kobj_attribute compass_id_attr =
__ATTR(compass_id, 0444, nct_item_show_compass, 0);
static const struct kobj_attribute gyroscope_id_attr =
__ATTR(gyroscope_id, 0444, nct_item_show_gyroscope, 0);
static const struct kobj_attribute light_id_attr =
__ATTR(light_id, 0444, nct_item_show_light, 0);
static const struct kobj_attribute charger_id_attr =
__ATTR(charger_id, 0444, nct_item_show_charger, 0);
static const struct kobj_attribute touch_id_attr =
__ATTR(touch_id, 0444, nct_item_show_touch, 0);
static const struct attribute *nct_item_attrs[] = {
&serial_number_attr.attr,
&wifi_mac_addr_attr.attr,
&bt_addr_attr.attr,
&cm_id_attr.attr,
&lbh_id_attr.attr,
&boardinfo_id_attr.attr,
&gps_id_attr.attr,
&lcd_id_attr.attr,
&accelerometer_id_attr.attr,
&compass_id_attr.attr,
&gyroscope_id_attr.attr,
&light_id_attr.attr,
&charger_id_attr.attr,
&touch_id_attr.attr,
NULL
};
static int __init tegra_nct_sysfs_init(void)
{
if (!tegra_nct_is_init()) {
pr_err("tegra_nct: not initialized\n");
return 0;
}
nct_kobj = kobject_create_and_add("tegra_nct", kernel_kobj);
if (!nct_kobj) {
pr_err("tegra_nct: failed to create sysfs nct object\n");
return 0;
}
if (sysfs_create_files(nct_kobj, nct_item_attrs)) {
pr_err("%s: failed to create nct item sysfs files\n", __func__);
kobject_del(nct_kobj);
nct_kobj = 0;
}
return 0;
}
late_initcall(tegra_nct_sysfs_init);