/* * drivers/arisc/arisc.c * * Copyright (c) 2012 Allwinner. * 2012-05-01 Written by sunny (sunny@allwinnertech.com). * 2012-10-01 Written by superm (superm@allwinnertech.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. * * 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. * */ #include #include "arisc_i.h" #ifdef CONFIG_PM static unsigned int arisc_debug_baudrate = 115200; unsigned int arisc_debug_dram_crc_en; unsigned int arisc_debug_dram_crc_srcaddr = 0x40000000; unsigned int arisc_debug_dram_crc_len = (1024 * 1024); unsigned int arisc_debug_dram_crc_error; unsigned int arisc_debug_dram_crc_total_count; unsigned int arisc_debug_dram_crc_error_count; unsigned int arisc_debug_level = 2; static ssize_t debug_mask_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { ssize_t size = 0; size = sprintf(buf, "%u\n", arisc_debug_level); return size; } static ssize_t debug_mask_store(struct kobject *dev, struct kobj_attribute *attr, const char *buf, size_t size) { u32 value = 0; sscanf(buf, "%u", &value); if ((value < 0) || (value > 3)) { pr_warn("invalid arisc debug mask [%d] to set\n", value); return size; } arisc_debug_level = value; arisc_set_debug_level(arisc_debug_level); pr_info("debug_mask change to %d\n", arisc_debug_level); return size; } static ssize_t debug_baudrate_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { ssize_t size = 0; size = sprintf(buf, "%u\n", arisc_debug_baudrate); return size; } static ssize_t debug_baudrate_store(struct kobject *dev, struct kobj_attribute *attr, const char *buf, size_t size) { u32 value = 0; sscanf(buf, "%u", &value); if ((value != 115200) && (value != 57600) && (value != 9600)) { pr_warn("invalid arisc uart baudrate [%d] to set\n", value); return size; } arisc_debug_baudrate = value; arisc_set_uart_baudrate(arisc_debug_baudrate); pr_info("debug_baudrate change to %d\n", arisc_debug_baudrate); return size; } static u32 time_to_wakeup_ms; static ssize_t time_to_wakeup_ms_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { ssize_t size = 0; size = sprintf(buf, "%u\n", time_to_wakeup_ms); return size; } static ssize_t time_to_wakeup_ms_store(struct kobject *dev, struct kobj_attribute *attr, const char *buf, size_t size) { u32 value = 0; sscanf(buf, "%u", &value); time_to_wakeup_ms = value; arisc_set_wakeup_source(SET_WAKEUP_TIME_MS(time_to_wakeup_ms)); pr_info("debug_baudrate change to %d\n", arisc_debug_baudrate); return size; } static ssize_t dram_crc_paras_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { ssize_t size = 0; size = sprintf(buf, "enable:0x%x srcaddr:0x%x lenght:0x%x\n", arisc_debug_dram_crc_en, arisc_debug_dram_crc_srcaddr, arisc_debug_dram_crc_len); return size; } static ssize_t dram_crc_paras_store(struct kobject *dev, struct kobj_attribute *attr, const char *buf, size_t size) { u32 dram_crc_en = 0; u32 dram_crc_srcaddr = 0; u32 dram_crc_len = 0; sscanf(buf, "%x %x %x\n", &dram_crc_en, &dram_crc_srcaddr, &dram_crc_len); if ((dram_crc_en != 0) && (dram_crc_en != 1)) { pr_warn("invalid arisc debug dram crc paras [%x] [%x] [%x] to set\n", dram_crc_en, dram_crc_srcaddr, dram_crc_len); return size; } arisc_debug_dram_crc_en = dram_crc_en; arisc_debug_dram_crc_srcaddr = dram_crc_srcaddr; arisc_debug_dram_crc_len = dram_crc_len; arisc_set_dram_crc_paras(arisc_debug_dram_crc_en, arisc_debug_dram_crc_srcaddr, arisc_debug_dram_crc_len); pr_info("dram_crc_en=0x%x, dram_crc_srcaddr=0x%x, dram_crc_len=0x%x\n", arisc_debug_dram_crc_en, arisc_debug_dram_crc_srcaddr, arisc_debug_dram_crc_len); return size; } static ssize_t dram_crc_result_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { arisc_query_dram_crc_result((unsigned long *)&arisc_debug_dram_crc_error, (unsigned long *)&arisc_debug_dram_crc_total_count, (unsigned long *)&arisc_debug_dram_crc_error_count); return sprintf(buf, "dram info:\n" \ " enable %u\n" \ " error %u\n" \ " total count %u\n" \ " error count %u\n" \ " src:%x\n" \ " len:0x%x\n", \ arisc_debug_dram_crc_en, arisc_debug_dram_crc_error, arisc_debug_dram_crc_total_count, arisc_debug_dram_crc_error_count, arisc_debug_dram_crc_srcaddr, arisc_debug_dram_crc_len); } static ssize_t dram_crc_result_store(struct kobject *dev, struct kobj_attribute *attr, const char *buf, size_t size) { u32 error = 0; u32 total_count = 0; u32 error_count = 0; sscanf(buf, "%u %u %u", &error, &total_count, &error_count); if ((error != 0) && (error != 1)) { pr_warn("invalid arisc dram crc result [%d] [%d] [%d] to set\n", error, total_count, error_count); return size; } arisc_debug_dram_crc_error = error; arisc_debug_dram_crc_total_count = total_count; arisc_debug_dram_crc_error_count = error_count; arisc_set_dram_crc_result((unsigned long)arisc_debug_dram_crc_error, (unsigned long)arisc_debug_dram_crc_total_count, (unsigned long)arisc_debug_dram_crc_error_count); pr_info("debug_dram_crc_result change to error:%u total count:%u error count:%u\n", arisc_debug_dram_crc_error, arisc_debug_dram_crc_total_count, arisc_debug_dram_crc_error_count); return size; } #define SUNXI_DEBUG_FILE(_name) \ static struct kobj_attribute _name##_attr = \ __ATTR(_name, 0644, _name##_show, _name##_store) SUNXI_DEBUG_FILE(debug_mask); SUNXI_DEBUG_FILE(debug_baudrate); SUNXI_DEBUG_FILE(time_to_wakeup_ms); SUNXI_DEBUG_FILE(dram_crc_paras); SUNXI_DEBUG_FILE(dram_crc_result); static struct attribute *sunxi_debug_attrs[] = { &debug_mask_attr.attr, &debug_baudrate_attr.attr, &time_to_wakeup_ms_attr.attr, &dram_crc_paras_attr.attr, &dram_crc_result_attr.attr, NULL }; static struct attribute_group sunxi_debug_group = { .attrs = sunxi_debug_attrs, }; static int __init arisc_init(void) { struct kobject *apm_kobj; int rc; pr_info("sunxi-pm debug v%s\n", DRV_VERSION); apm_kobj = kobject_create_and_add("sunxi_debug", power_kobj); if (!apm_kobj) return -ENOMEM; rc = sysfs_create_group(apm_kobj, &sunxi_debug_group); if (rc) kobject_put(apm_kobj); return rc; } #else static int __init arisc_init(void) { return 0; } #endif /* CONFIG_PM */ subsys_initcall(arisc_init); MODULE_DESCRIPTION("SUNXI POWER MANAGEMENT"); MODULE_AUTHOR("Superm Wu "); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION);