ONIE_ROOT=$(realpath $(dirname $0)/../../../)
MACHINE=$(basename $(dirname $(realpath $0)))
MACHINEROOT=$ONIE_ROOT/machine/huaqin
PARAMS=$*
PARAMS=${PARAMS:-help}
BUILD_IMAGE=$ONIE_ROOT/build/imagesif [[ $PARAMS =~ .*rmbuild.* ]]; thenecho "Delete all the build directories, which may require root permission"sudo rm -rf $ONIE_ROOT/buildexit
fimake -C $ONIE_ROOT/build-config -j64 MACHINEROOT=$MACHINEROOT MACHINE=$MACHINE $PARAMSif [[ $PARAMS =~ .*help.* ]]; thenecho "The following is the customized help of Huaqin : "echoecho "./build.sh clean : Delete compiled image"echo "./build.sh rmbuild : Delete everything in the current build"
fiif [[ $PARAMS =~ .*all.* ]] || [[ $PARAMS =~ .*demo.* ]]; thenecho "Build images path: $BUILD_IMAGE"ls -l $BUILD_IMAGE/*${MACHINE}* | sed "s#$BUILD_IMAGE/##g"
fi
// cpld_h.c : lpc访问COMe/Baseboard CPLD : CPLD , LED , WatchDog
#include "common_hq.h"
#include
#define CPLD_DRIVER_NAME "sys_cpld"
#define CPLD_DRIVER_VER "0.0.1"
/*** CPLD register address for read and write.*/
/** Base CPLD:0xA100 ~ 0xA1DF* COMe CPLD:0xA1E0 ~ 0xA1FF* */
#define BASE_CPLD_ADDR 0xA100
#define COME_CPLD_ADDR 0xA1E0
#define VERSION_ADDR 0xA100#define BASE_PCB_VER_ADDR 0xA100
#define BASE_H_VER_ADDR 0xA101
#define BASE_M_VER_ADDR 0xA102
#define BASE_L_VER_ADDR 0xA103
#define BASE_SCRATCH_ADDR 0xA104#define COME_PCB_VER_ADDR 0xA1E0
#define COME_H_VER_ADDR 0xA1E1
#define COME_M_VER_ADDR 0xA1E2
#define COME_L_VER_ADDR 0xA1E3
#define COME_SCRATCH_ADDR 0xA1E4#define CPLD_REGISTER_SIZE 0xFF
#define CPLD_TOTAL_NUMBER 4/*watchdog*/
#define BASE_REG_ADDR_WD_EN 0xA190
#define BASE_REG_ADDR_WD_LTIME 0xA191
#define BASE_REG_ADDR_WD_HTIME 0xA192
#define BASE_REG_ADDR_WD_KICK 0xA193
#define BASE_REG_ADDR_WD_FOUN 0xA194
#define BASE_REG_ADDR_WD_STAE 0xA195 //status
#define BASE_REG_ADDR_WD_CLEAR 0xA196
#define BASE_REG_ADDR_WD_LTIMELEFT 0xA197
#define BASE_REG_ADDR_WD_HTIMELEFT 0xA198/*sysled*/
#define PSU_LED_ADDR 0xA140
#define SYS_LED_ADDR 0xA141
#define Alarm_LED_ADDR 0xA142
#define Fan_LED_ADDR 0xA143
#define BMC_LED_ADDR 0xA144enum
{DARK,GREEN,YELLOW,RED,BLUE,GREEN_LIGHT_FLASHING,YELLOW_LIGHT_FLASHING,RED_LIGHT_FLASHING,BLUE_LIGHT_FLASHING
};int set_bit_value(int value,int bit,int status);
int get_bit_value(int value,int bit);/******************************************************watchdog*******************************************************************/
ssize_t get_main_watchdog_identify(char *buf, size_t count)
{return sprintf(buf,"CPU_wdt\n");
}
EXPORT_SYMBOL(get_main_watchdog_identify);ssize_t get_main_watchdog_state(char *buf, size_t count)
{int data=inb(BASE_REG_ADDR_WD_EN);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",BASE_REG_ADDR_WD_EN,inb(BASE_REG_ADDR_WD_EN));data = get_bit_value(data,0);data=sprintf(buf,"%x\n",data); //转为16进制return data;
}
EXPORT_SYMBOL(get_main_watchdog_state);ssize_t get_main_watchdog_timeleft(char *buf, size_t count)
{int data_ligh = inb(BASE_REG_ADDR_WD_HTIMELEFT);// printk(KERN_INFO "Baseboard CPLD addr BASE_REG_ADDR_WD_HTIME :%.2x,value: %.2x \n",BASE_REG_ADDR_WD_HTIMELEFT,data_ligh);int data_low = inb(BASE_REG_ADDR_WD_LTIMELEFT);// printk(KERN_INFO "Baseboard CPLD addr BASE_REG_ADDR_WD_LTIME:%.2x,value: %.2x \n",BASE_REG_ADDR_WD_LTIMELEFT,data_low);int data=(data_ligh << 8 )+data_low;// printk(KERN_INFO "data :%.2x \n",data);data=data/1000;data=sprintf(buf,"%d\n",data);return data;
}
EXPORT_SYMBOL(get_main_watchdog_timeleft);ssize_t get_main_watchdog_timeout(char *buf, size_t count)
{int data_ligh = inb(BASE_REG_ADDR_WD_HTIME);// printk(KERN_INFO "Baseboard CPLD addr BASE_REG_ADDR_WD_HTIME :%.2x,value: %.2x \n",BASE_REG_ADDR_WD_HTIME,data_ligh);int data_low = inb(BASE_REG_ADDR_WD_LTIME);// printk(KERN_INFO "Baseboard CPLD addr BASE_REG_ADDR_WD_LTIME:%.2x,value: %.2x \n",BASE_REG_ADDR_WD_LTIME,data_low);int data=(data_ligh << 8 )+data_low; //拼接// printk(KERN_INFO "data :%.2x \n",data);data=data/1000; //毫秒变成秒data=sprintf(buf,"%d\n",data);return data;
}
EXPORT_SYMBOL(get_main_watchdog_timeout);int set_main_watchdog_timeout(int value)
{int value_ms = value * 1000 ; //秒变成毫秒outb(value_ms&0xff ,BASE_REG_ADDR_WD_LTIME); //outb写,取低八位outb((value_ms>>8)&0xff ,BASE_REG_ADDR_WD_HTIME);return;
}
EXPORT_SYMBOL(set_main_watchdog_timeout);static void feed_watchdog(void)
{int addr,value;addr = BASE_REG_ADDR_WD_KICK;value = inb(addr); // 读value = set_bit_value(value,0,0); // 设 0x7cvalue = set_bit_value(value,1,0);value = set_bit_value(value,2,1);value = set_bit_value(value,3,1);value = set_bit_value(value,4,1);value = set_bit_value(value,5,1);value = set_bit_value(value,6,1);value = set_bit_value(value,7,0);outb(value,addr); // 写
}ssize_t get_main_watchdog_enable_status(char *buf, size_t count)
{int addr,value;addr = BASE_REG_ADDR_WD_EN;value=inb(addr);value = get_bit_value(value,0); //看最后一位return sprintf(buf,"%02X\n", value);
}
EXPORT_SYMBOL(get_main_watchdog_enable_status);int set_main_watchdog_enable_status(int status)
{int addr,value;addr = BASE_REG_ADDR_WD_EN;value = inb(addr);switch(status){case 0:value = set_bit_value(value,0,0);outb(value,addr);break;case 1:value = set_bit_value(value,0,1);outb(value,addr);feed_watchdog();break;default:return -ENOSYS;}return status;
}
EXPORT_SYMBOL(set_main_watchdog_enable_status);/******************************************************************************new enable node***********************************/
ssize_t get_watchdog_enable_status(struct device *dev, struct device_attribute *attr, char *buf)
{size_t count=0;return get_main_watchdog_enable_status(buf, count);
}
static ssize_t set_watchdog_enable_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{int value,rc = 0;rc = kstrtoint(buf,10,&value);if (rc != 0) {return size;}set_main_watchdog_enable_status(value);return size;
}
static struct device_attribute watchdog_enable_attr = __ATTR(enable, S_IRUGO | S_IWUSR,get_watchdog_enable_status,set_watchdog_enable_status);/****************************************************************************new timeout node*******************************/
ssize_t get_watchdog_timeout(struct device *dev, struct device_attribute *attr, char *buf)
{return get_main_watchdog_timeout(buf,NULL);
}
static ssize_t set_watchdog_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{int value,rc = 0;rc = kstrtoint(buf,10,&value);if (rc != 0) {return size;}set_main_watchdog_timeout(value);return size;
}
static struct device_attribute watchdog_timeout_attr = __ATTR(timeout, S_IRUGO | S_IWUSR,get_watchdog_timeout,set_watchdog_timeout);/******************************************************************************new feed node*******************************/
static ssize_t hq_set_watchdog_feed(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{int data,rc = 0;rc = kstrtoint(buf,16,&data);if (rc != 0) {return size;}// printk(KERN_INFO "Baseboard CPLD addr BASE_REG_ADDR_WD_KICK :%.2x,value: %.2x \n",BASE_REG_ADDR_WD_KICK,data);if(data==0x7c){outb(data,BASE_REG_ADDR_WD_KICK);// printk(KERN_INFO "Baseboard CPLD feed dog getreg value : %.2x \n",inb(BASE_REG_ADDR_WD_KICK));}else{return -EINVAL;}return size;
}
static struct device_attribute watchdog_feed_attt = __ATTR(feed, S_IRUGO | S_IWUSR, NULL, hq_set_watchdog_feed);/************************************************************************new strategy node*******************************/
ssize_t hq_get_watchdog_strategy(struct device *dev, struct device_attribute *attr, char *buf)
{return sprintf(buf,"%0.2x\n",inb(BASE_REG_ADDR_WD_FOUN));
}
static ssize_t hq_set_watchdog_strategy(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{int data,rc = 0;rc = kstrtoint(buf,16,&data);if (rc != 0) {return size;}if((data==0x01) || (data ==0x02)){outb(data,BASE_REG_ADDR_WD_FOUN);// printk(KERN_INFO " hq_set_watchdog_strategy addr value : %.2x \n",inb(BASE_REG_ADDR_WD_FOUN));}else{return -EINVAL;}return size;
}
static struct device_attribute watchdog_strategy_attr = __ATTR(strategy, S_IRUGO | S_IWUSR,hq_get_watchdog_strategy ,hq_set_watchdog_strategy);/********************************************************************new timeout_counts node*******************************/
ssize_t hq_get_watchdog_timeout_times(struct device *dev, struct device_attribute *attr, char *buf)
{return sprintf(buf,"%d\n",inb(BASE_REG_ADDR_WD_STAE));
}
static struct device_attribute watchdog_timeout_counts_attr = __ATTR(timeout_counts, S_IWUSR|S_IRUGO,hq_get_watchdog_timeout_times, NULL);/********************************************************************new timeout_reset node*******************************/
static ssize_t hq_set_watchdog_timeout_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{int data,rc = 0;rc = kstrtoint(buf,16,&data);if (rc != 0) {return size;}if(data==1){outb(data,BASE_REG_ADDR_WD_KICK);}else{return -EINVAL;}return size;
}
static struct device_attribute watchdog_timeout_reset_attr = __ATTR(timeout_reset, S_IRUGO | S_IWUSR,NULL ,hq_set_watchdog_timeout_reset);static struct attribute *watchdog_dir_attrs[] = {&watchdog_enable_attr.attr,&watchdog_timeout_attr.attr,&watchdog_feed_attt.attr,&watchdog_strategy_attr.attr,&watchdog_timeout_counts_attr.attr,&watchdog_timeout_reset_attr.attr,NULL
};static struct attribute_group watchdog_attr_group = { // 在下面cpld_hq_drv_probe函数里: kobject_create_and_add, sysfs_create_group.attrs = watchdog_dir_attrs,
};
/******************************************************watchdog end*********************************************************************************//******************************************************sysled begain*******************************************************************************/
int set_sysled_state(int status,char *names)
{int addr,value;if(strcmp(names,"PSU")==0){addr=PSU_LED_ADDR;}else if(strcmp(names,"SYS")==0){addr=SYS_LED_ADDR;}else if(strcmp(names,"Alarm")==0){addr=Alarm_LED_ADDR;}else if(strcmp(names,"Fan")==0){addr=Fan_LED_ADDR;}else if(strcmp(names,"BMC")==0){addr=BMC_LED_ADDR;}else{return -ENOSYS;}value=inb(addr);switch(status){case DARK:value=set_bit_value(value,6,1);value=set_bit_value(value,0,1);value=set_bit_value(value,1,0);outb(value,addr);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",addr,inb(addr));break;case GREEN:value=set_bit_value(value,6,1);value=set_bit_value(value,4,0);value=set_bit_value(value,5,0);value=set_bit_value(value,1,0);value=set_bit_value(value,0,0);outb(value,addr);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",addr,inb(addr));break;case YELLOW:value=set_bit_value(value,6,1);value=set_bit_value(value,4,1);value=set_bit_value(value,5,0);value=set_bit_value(value,1,0);value=set_bit_value(value,0,0);outb(value,addr);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",addr,inb(addr));break; case RED:return -ENOSYS;case BLUE:return -ENOSYS;case GREEN_LIGHT_FLASHING:value=set_bit_value(value,6,1);value=set_bit_value(value,4,0);value=set_bit_value(value,5,0);value=set_bit_value(value,1,1);value=set_bit_value(value,0,0);outb(value,addr);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",addr,inb(addr));break;case YELLOW_LIGHT_FLASHING:value=set_bit_value(value,6,1);value=set_bit_value(value,4,1);value=set_bit_value(value,5,0);value=set_bit_value(value,1,1);value=set_bit_value(value,0,0);outb(value,addr);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",addr,inb(addr));break;case RED_LIGHT_FLASHING:return -ENOSYS;case BLUE_LIGHT_FLASHING:return -ENOSYS;default:return -ENOSYS;}return 1;
}
EXPORT_SYMBOL(set_sysled_state);ssize_t get_sysled_state(char *buf, size_t count,char *names)
{int addr,value;int len=-1;if(strcmp(names,"PSU")==0){addr=PSU_LED_ADDR;}else if(strcmp(names,"SYS")==0){addr=SYS_LED_ADDR;}else if(strcmp(names,"Alarm")==0){addr=Alarm_LED_ADDR;}else if(strcmp(names,"Fan")==0){addr=Fan_LED_ADDR;}else if(strcmp(names,"BMC")==0){addr=BMC_LED_ADDR;}else{return -ENOSYS;}value=inb(addr);if(get_bit_value(value,0)==1 && get_bit_value(value,1)==0){len=sprintf(buf,"dark\n");return len;}else if(get_bit_value(value,0)==0 && get_bit_value(value,1)==0){//buf chang liang 常亮if(get_bit_value(value,4)==0 && get_bit_value(value,5)==0){len=sprintf(buf,"green\n");return len;}else if(get_bit_value(value,4)==1 && get_bit_value(value,5)==0){len=sprintf(buf,"yellow\n");return len;}else{;}}else if(get_bit_value(value,0)==0 && get_bit_value(value,1)==1){//buf 闪烁if(get_bit_value(value,4)==0 && get_bit_value(value,5)==0){len=sprintf(buf,"green light flashing\n");return len;}else if(get_bit_value(value,4)==1 && get_bit_value(value,5)==0){len=sprintf(buf,"yellow light flashing\n");return len;}else{;}}else{return -ENOSYS;}
}
EXPORT_SYMBOL(get_sysled_state);int get_bit_value(int value,int bit)
{if(value<0 || value>0xff || bit<0 || bit>7){return -1;}int data ;data=value >> bit & 0x01; // 右移bit位并取最后一位return data;
}int set_bit_value(int value,int bit,int status)
{if(value<0 || value>0xff || bit<0 || bit>7|| status<0 || status>1){return -1;}else{if(status==0) //将1111 1111第二位(从0开始即第三位)置为0{value=(~(1<value = (1<;}}
}
/*****************************************************sysled end*************************************************************************************//***********************************************CPLD begain*******************************************************************************************/
int get_board_cpld_number(void)
{/* add vendor codes here */return CPLD_TOTAL_NUMBER;
}
EXPORT_SYMBOL(get_board_cpld_number);/** demo_get_main_board_cpld_alias - Used to identify the location of cpld,* @cpld_index: start with 1* @buf: Data receiving buffer* @count: length of buf** This function returns the length of the filled buffer,* if not support this attributes filled "NA" to buf,* otherwise it returns a negative value on failed.*/
ssize_t get_board_cpld_alias(unsigned int cpld_index, char *buf, size_t count)
{/* add vendor codes here */int len = -1 ;switch(cpld_index){case 1 :len=sprintf(buf,"Base board CPLD\n");break ;case 2 :len=sprintf(buf,"Come CPLD\n");break ;default:len = -1 ;break;}return len;
}
EXPORT_SYMBOL(get_board_cpld_alias);/** demo_get_main_board_cpld_type - Used to get cpld model name* @cpld_index: start with 1* @buf: Data receiving buffer* @count: length of buf** This function returns the length of the filled buffer,* if not support this attributes filled "NA" to buf,* otherwise it returns a negative value on failed.*/
ssize_t get_board_cpld_type(unsigned int cpld_index, char *buf, size_t count)
{/* add vendor codes here */int len = -1 ;switch(cpld_index){case 1 :len=sprintf(buf,"LCMXO3LF-4300C-5BG400C CPLD\n");break ;case 2 :len=sprintf(buf,"LCMXO3LF-2100C-5BG400C CPLD\n");break ;default:len = -1 ;break;}return len;
}
EXPORT_SYMBOL(get_board_cpld_type);/** demo_get_main_board_cpld_firmware_version - Used to get cpld firmware version,* @cpld_index: start with 1* @buf: Data receiving buffer* @count: length of buf** This function returns the length of the filled buffer,* if not support this attributes filled "NA" to buf,* otherwise it returns a negative value on failed.*/
ssize_t get_board_cpld_firmware_version(unsigned int cpld_index, char *buf, size_t count)
{/* add vendor codes here */int len = -1; switch(cpld_index){case 1:printk(KERN_INFO "BASE CPLD H version:0x%2.2x\n", inb(BASE_H_VER_ADDR));printk(KERN_INFO "BASE CPLD M version:0x%2.2x\n", inb(BASE_M_VER_ADDR));printk(KERN_INFO "BASE CPLD L version:0x%2.2x\n", inb(BASE_L_VER_ADDR)); len = sprintf(buf,"%x.%x.%x\n", inb(BASE_H_VER_ADDR),inb(BASE_M_VER_ADDR),inb(BASE_L_VER_ADDR));break;case 2:printk(KERN_INFO "COME CPLD H version:0x%2.2x\n", inb(COME_H_VER_ADDR));printk(KERN_INFO "COME CPLD M version:0x%2.2x\n", inb(COME_M_VER_ADDR));printk(KERN_INFO "COME CPLD L version:0x%2.2x\n", inb(COME_L_VER_ADDR));len = sprintf(buf,"%x.%x.%x\n", inb(COME_H_VER_ADDR),inb(COME_M_VER_ADDR),inb(COME_L_VER_ADDR)); break;default:len = -1;break;}return len;
}
EXPORT_SYMBOL(get_board_cpld_firmware_version);/** demo_get_main_board_cpld_board_version - Used to get cpld board version,* @cpld_index: start with 1* @buf: Data receiving buffer* @count: length of buf** This function returns the length of the filled buffer,* if not support this attributes filled "NA" to buf,* otherwise it returns a negative value on failed.*/
ssize_t get_board_cpld_board_version(unsigned int cpld_index, char *buf, size_t count)
{/* add vendor codes here */int len = -1; switch(cpld_index){case 1:len = sprintf(buf,"%02X\n", inb(BASE_PCB_VER_ADDR));break;case 2:len = sprintf(buf,"%02X\n", inb(COME_PCB_VER_ADDR));break;default:len = -1;break;}return len;
}
EXPORT_SYMBOL(get_board_cpld_board_version);/** demo_get_main_board_cpld_test_reg - Used to test cpld register read* filled the value to buf, value is hexadecimal, start with 0x* @cpld_index: start with 1* @buf: Data receiving buffer* @count: length of buf** This function returns the length of the filled buffer,* if not support this attributes filled "NA" to buf,* otherwise it returns a negative value on failed.*/
ssize_t get_board_cpld_test_reg(unsigned int cpld_index, char *buf, size_t count)
{/* add vendor codes here */int len = -1 ;switch(cpld_index){case 1 :len=sprintf(buf,"%02x\n",inb(BASE_SCRATCH_ADDR));break ;case 2 :len=sprintf(buf,"%02x\n",inb(COME_SCRATCH_ADDR));break ;default:len = -1 ;break;}return len;
}
EXPORT_SYMBOL(get_board_cpld_test_reg);/** demo_set_main_board_cpld_test_reg - Used to test cpld register write* @cpld_index: start with 1* @value: value write to cpld** This function returns 0 on success,* otherwise it returns a negative value on failed.*/
int set_board_cpld_test_reg(unsigned int cpld_index, unsigned int value)
{/* add vendor codes here */int ret = -1 ;switch(cpld_index){case 1 :outb(value,BASE_SCRATCH_ADDR);ret = 1;break ;case 2 :outb(value,COME_SCRATCH_ADDR);ret = 1;break ;default: ret = -1 ;break;}return ret;
}
EXPORT_SYMBOL(set_board_cpld_test_reg);
/********************************************************CPLD end***********************************************************************/struct cpld_hq_data {struct mutex cpld_lock;uint16_t read_addr;uint16_t base_addr;
};struct cpld_hq_data *cpld_data;static ssize_t get_cpld_reg_address(struct device *dev, struct device_attribute *attr, char *buf)
{int len = 0;// CPLD register is one bytemutex_lock(&cpld_data->cpld_lock);len = sprintf(buf, "0x%2.2x\n",inb(cpld_data->read_addr));mutex_unlock(&cpld_data->cpld_lock);return len;
}/*** Store the register address* @param buf address wanted to be read value of* @return number of bytes stored, or an error code*/
static ssize_t set_cpld_reg_address(struct device *dev, struct device_attribute *devattr,const char *buf, size_t count)
{uint32_t addr;char *last;mutex_lock(&cpld_data->cpld_lock);addr = (uint32_t)strtoul(buf, &last, 16);if (addr == 0 && buf == last) {return -EINVAL;}cpld_data->read_addr = cpld_data->base_addr + addr;mutex_unlock(&cpld_data->cpld_lock);return count;
}static DEVICE_ATTR( getreg, 0600, get_cpld_reg_address, set_cpld_reg_address);static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr,const char *buf, size_t count)
{// CPLD register is one byteuint16_t addr;uint8_t value;char *tok;char clone[count+1];char *pclone = clone;char *last;strcpy(clone, buf);mutex_lock(&cpld_data->cpld_lock);tok = strsep((char**)&pclone, " ");if(tok == NULL){mutex_unlock(&cpld_data->cpld_lock);return -EINVAL;}addr = (uint16_t)strtoul(tok, &last,16);if(addr == 0 && tok == last){mutex_unlock(&cpld_data->cpld_lock);return -EINVAL;}tok = strsep((char**)&pclone, " ");if(tok == NULL){mutex_unlock(&cpld_data->cpld_lock);return -EINVAL;}value = (uint8_t)strtoul(tok, &last,16);if(value == 0 && tok == last){mutex_unlock(&cpld_data->cpld_lock);return -EINVAL;}outb(value, cpld_data->base_addr + addr);mutex_unlock(&cpld_data->cpld_lock);return count;
}
//static DEVICE_ATTR_WO(setreg);
static DEVICE_ATTR( setreg, 0200, NULL , setreg_store);
/*** Read all CPLD register in binary mode.* @return number of byte read.*/
static ssize_t dump_read(struct file *filp, struct kobject *kobj,struct bin_attribute *attr, char *buf,loff_t off, size_t count)
{unsigned long i = 0;ssize_t status;mutex_lock(&cpld_data->cpld_lock);begin:if(i < count){buf[i++] = inb(VERSION_ADDR + off);off++;msleep(1);goto begin;}status = count;exit:mutex_unlock(&cpld_data->cpld_lock);return status;
}static BIN_ATTR_RO(dump, CPLD_REGISTER_SIZE);static struct attribute *cpld_hq_attrs[] = {&dev_attr_getreg.attr,&dev_attr_setreg.attr,NULL,
};static struct bin_attribute *cpld_hq_bin_attrs[] = {&bin_attr_dump,NULL,
};static struct attribute_group cpld_hq_attrs_group = {.attrs = cpld_hq_attrs,.bin_attrs = cpld_hq_bin_attrs,
};static struct resource cpld_hq_resources[] = {{.start = 0xA100,.end = 0xA1FF,.flags = IORESOURCE_IO,},
};static void cpld_hq_dev_release( struct device * dev)
{return;
}static struct platform_device cpld_hq_dev = {.name = CPLD_DRIVER_NAME,.id = -1,.num_resources = ARRAY_SIZE(cpld_hq_resources),.resource = cpld_hq_resources,.dev = {.release = cpld_hq_dev_release,}
};static int cpld_hq_drv_remove(struct platform_device *pdev)
{sysfs_remove_group(&pdev->dev.kobj, &cpld_hq_attrs_group);return 0;
}static struct kobject *watchdog = NULL;
static int cpld_hq_drv_probe(struct platform_device *pdev)
{struct resource *resource;int err = 0;cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_hq_data), GFP_KERNEL);if(!cpld_data)return -ENOMEM;mutex_init(&cpld_data->cpld_lock);cpld_data ->read_addr = VERSION_ADDR;cpld_data ->base_addr = BASE_CPLD_ADDR;resource = platform_get_resource(pdev, IORESOURCE_IO, 0);if(unlikely(!resource)){printk(KERN_ERR "Specified Resource Not Available...\n");return -ENODEV;}err = sysfs_create_group(&pdev->dev.kobj, &cpld_hq_attrs_group);if(err) {printk(KERN_ERR "Cannot create sysfs for system CPLD\n");return err;}printk(KERN_INFO "CPLD Probe driver");printk(KERN_INFO "BASE CPLD Address:ox%2.2x\n", BASE_CPLD_ADDR);printk(KERN_INFO "COMe CPLD Address:ox%2.2x\n", COME_CPLD_ADDR);printk(KERN_INFO "BASE CPLD PCB version:0x%2.2x\n", inb(BASE_PCB_VER_ADDR));printk(KERN_INFO "BASE CPLD H version:0x%2.2x\n", inb(BASE_H_VER_ADDR));printk(KERN_INFO "BASE CPLD M version:0x%2.2x\n", inb(BASE_M_VER_ADDR));printk(KERN_INFO "BASE CPLD L version:0x%2.2x\n", inb(BASE_L_VER_ADDR));printk(KERN_INFO "COME CPLD PCB version:0x%2.2x\n", inb(COME_PCB_VER_ADDR));printk(KERN_INFO "COME CPLD H version:0x%2.2x\n", inb(COME_H_VER_ADDR));printk(KERN_INFO "COME CPLD M version:0x%2.2x\n", inb(COME_M_VER_ADDR));printk(KERN_INFO "COME CPLD L version:0x%2.2x\n", inb(COME_L_VER_ADDR)); printk(KERN_INFO "GPIO base address:0x%x\n", inl(0x48));//watchdogwatchdog = kobject_create_and_add("watchdog",&pdev->dev.kobj);if (!watchdog){return -ENOMEM;}if(sysfs_create_group(watchdog,&watchdog_attr_group)){printk(KERN_INFO"watchdog_attr_group failed\n");return -1;}/*int ret;ret=watchdog_root_create();if (ret < 0) {WDT_ERR("watchdog create error.\n");return ret;}*/return 0;}static struct platform_driver cpld_hq_drv = {.probe = cpld_hq_drv_probe,.remove = __exit_p(cpld_hq_drv_remove),.driver = {.name = CPLD_DRIVER_NAME,},
};static int __init cpld_hq_init(void)
{/*Register Platform device and Platform Driver*/platform_device_register(&cpld_hq_dev);platform_driver_register(&cpld_hq_drv);printk(KERN_INFO "%s: version %s loaded successfully\n", CPLD_DRIVER_NAME, CPLD_DRIVER_VER);return 0;
}static void __exit cpld_hq_exit(void)
{/*Unregister Platform device and Platform Driver*/platform_driver_unregister(&cpld_hq_drv);platform_device_unregister(&cpld_hq_dev);printk(KERN_INFO "%s: unloaded successfully\n", CPLD_DRIVER_NAME);
}module_init(cpld_hq_init);
module_exit(cpld_hq_exit);MODULE_AUTHOR("Huaqin Technology Co.,Ltd.");
MODULE_DESCRIPTION("Hua Qin Common CPLD");
MODULE_VERSION(CPLD_DRIVER_VER);
MODULE_LICENSE("GPL");
#include "common_hq.h" //相当于复制进来static int demo_get_main_board_cpld_number(void)
{/* add vendor codes here */return get_board_cpld_number();
}static ssize_t demo_get_main_board_cpld_alias(unsigned int cpld_index, char *buf, size_t count)
{/* add vendor codes here */if((cpld_index == 1) || (cpld_index == 2)){return get_board_cpld_alias(cpld_index, buf, count);}else if((cpld_index == 3) || (cpld_index == 4)){return get_switch_board_cpld_alias(cpld_index, buf, count);}else{return -EINVAL;}
}

# 外层Makefile
PWD = $(shell pwd)
SYSFS_OUT_PUT := $(PWD)/build
sysfs_out_put_dir := $(SYSFS_OUT_PUT)/S3IP_sysfs/
export sysfs_out_put_dir
# KERNEL_SRC=/lib/modules/$(shell uname -r)
KERNEL_SRC=/home_a/yutao/sysfs/my/header/usr/src/linux-headers-4.9.0-14-2-amd64
export KERNEL_SRCSYSFS_DRIVER_DIR = $(PWD)/s3ip_sysfs_frame
SWITCH_DRIVER_DIR = $(PWD)/demo_driver
HQ_DRIVER_DIR = $(PWD)/s3ip_hq_driver
KBUILD_EXTRA_SYMBOLS += $(HQ_DRIVER_DIR)/Module.symvers
KBUILD_EXTRA_SYMBOLS += $(SYSFS_DRIVER_DIR)/Module.symvers
KBUILD_EXTRA_SYMBOLS += $(SWITCH_DRIVER_DIR)/Module.symvers
export KBUILD_EXTRA_SYMBOLSall :$(MAKE) -C $(HQ_DRIVER_DIR)$(MAKE) -C $(SYSFS_DRIVER_DIR)$(MAKE) -C $(SWITCH_DRIVER_DIR)clean :-rm -rf $(SYSFS_OUT_PUT)$(MAKE) -C $(HQ_DRIVER_DIR) clean$(MAKE) -C $(SYSFS_DRIVER_DIR) clean$(MAKE) -C $(SWITCH_DRIVER_DIR) cleaninstall:install -d $(DESTDIR)/lib/modules/s3ip/install -D $(sysfs_out_put_dir)/*.ko \$(DESTDIR)/lib/modules/s3ip/install -D scripts/s3ip_load.py \$(DESTDIR)/$(prefix)/bin/s3ip_load.pyinstall -D scripts/s3ip_sysfs_conf.json \$(DESTDIR)/etc/s3ip/s3ip_sysfs_conf.jsoninstall -D scripts/s3ip_sysfs_tool.sh \$(DESTDIR)/$(prefix)/bin/s3ip_sysfs_tool.shinstall -D scripts/s3ip-sysfs.service \$(DESTDIR)/etc/systemd/system/s3ip-sysfs.serviceuninstall:-rm -f $(DESTDIR)$(prefix)/bin/s3ip_load.py-rm -f $(DESTDIR)/lib/modules/s3ip/-rm -f $(DESTDIR)/etc/s3ip-rm -f $(DESTDIR)/$(prefix)/bin/s3ip_sysfs_tool.sh-rm -f $(DESTDIR)/etc/systemd/system/s3ip-sysfs.service
# 里层Makefile
PWD = $(shell pwd)
MAKEFILE_FILE_PATH = $(abspath $(lastword $(MAKEFILE_LIST)))
DEV_SYSFS_HEADER_DIR = $(abspath $(MAKEFILE_FILE_PATH)/../../s3ip_sysfs_frame/include)
SWITCH_DVR_HEADER_DIR = $(abspath $(MAKEFILE_FILE_PATH)/../../demo_driver/include)
HQ_DVR_HEADER_DIR = $(abspath $(MAKEFILE_FILE_PATH)/../../s3ip_hq_driver/include)
EXTRA_CFLAGS:= -I$(M)/include
EXTRA_CFLAGS+= -I$(DEV_SYSFS_HEADER_DIR)
EXTRA_CFLAGS+= -I$(SWITCH_DVR_HEADER_DIR)
EXTRA_CFLAGS+= -I$(HQ_DVR_HEADER_DIR)
EXTRA_CFLAGS+= -Wallobj-m := cpld_hq.o
obj-m += fpga_i2c_adapter.o
obj-m += i2c-ocores.o
obj-m += mc24lc64t.o
obj-m += optoe.o
obj-m += switchboard.oall:$(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules@if [ ! -d $(sysfs_out_put_dir) ]; then mkdir -p $(sysfs_out_put_dir) ;ficp -p $(PWD)/*.ko $(sysfs_out_put_dir)
clean:rm -f $(PWD)/*.o $(PWD)/*.ko $(PWD)/*.mod.c $(PWD)/.*.cmd rm -f $(PWD)/Module.markers $(PWD)/Module.symvers $(PWD)/modules.order rm -rf $(PWD)/.tmp_versionsrm -rf $(PWD)/.cache.mkrm -rf $(PWD)/*.mod
#ifndef _COMMON_HQ_H_
#define _COMMON_HQ_H_#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include extern int get_board_cpld_number(void);
extern ssize_t get_board_cpld_alias(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t get_board_cpld_type(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t get_board_cpld_firmware_version(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t get_board_cpld_board_version(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t get_board_cpld_test_reg(unsigned int cpld_index, char *buf, size_t count);
extern int set_board_cpld_test_reg(unsigned int cpld_index, unsigned int value);extern int get_board_fpga_number(void);
extern ssize_t get_board_fpga_alias(unsigned int fpga_index, char *buf, size_t count);
extern ssize_t get_board_fpga_type(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t get_board_fpga_firmware_version(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t get_board_fpga_board_version(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t get_board_fpga_test_reg(unsigned int cpld_index, char *buf, size_t count);
extern int set_board_fpga_test_reg(unsigned int cpld_index, unsigned int value);extern ssize_t get_switch_board_cpld_alias(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t get_switch_board_cpld_type(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t get_switch_board_cpld_firmware_version(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t get_switch_board_cpld_board_version(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t get_switch_board_cpld_test_reg(unsigned int cpld_index, char *buf, size_t count);
extern ssize_t set_switch_board_cpld_test_reg(unsigned int cpld_index, unsigned int value);//QSFP
extern int get_main_eth_number(void);
extern ssize_t get_main_transceiver_power_on_status(char *buf, size_t count);
extern int set_main_transceiver_power_on_status(int status);
extern ssize_t get_main_eth_power_on_status(unsigned int eth_index, char *buf, size_t count);
extern int set_main_eth_power_on_status(unsigned int eth_index, int status);
extern ssize_t get_main_eth_tx_fault_status(unsigned int eth_index, char *buf, size_t count);
extern ssize_t get_main_eth_tx_disable_status(unsigned int eth_index, char *buf, size_t count);
extern int set_main_eth_tx_disable_status(unsigned int eth_index, int status);
extern ssize_t get_main_eth_present_status(unsigned int eth_index, char *buf, size_t count);
extern ssize_t get_main_eth_rx_los_status(unsigned int eth_index, char *buf, size_t count);
extern ssize_t get_main_eth_reset_status(unsigned int eth_index, char *buf, size_t count);
extern int set_main_eth_reset_status(unsigned int eth_index, int status);
extern ssize_t get_main_eth_low_power_mode_status(unsigned int eth_index, char *buf, size_t count);
extern ssize_t get_main_eth_interrupt_status(unsigned int eth_index, char *buf, size_t count);
extern int get_main_eth_eeprom_size(unsigned int eth_index);
extern ssize_t read_main_eth_eeprom_data(unsigned int eth_index, char *buf, loff_t offset, size_t count);
extern ssize_t write_main_eth_eeprom_data(unsigned int eth_index, char *buf, loff_t offset, size_t count);//sysled
extern int set_sysled_state(int status,char *names);
extern ssize_t get_sysled_state(char *buf, size_t count,char *names);//watchdog
extern ssize_t get_main_watchdog_identify(char *buf, size_t count);
extern ssize_t get_main_watchdog_state(char *buf, size_t count);
extern ssize_t get_main_watchdog_timeleft(char *buf, size_t count);
extern ssize_t get_main_watchdog_timeout(char *buf, size_t count);
extern int set_main_watchdog_timeout(int value);
extern ssize_t get_main_watchdog_enable_status(char *buf, size_t count);
extern int set_main_watchdog_enable_status(int value);#endif
cpld_hq.c
// cpld_hq.c: lpc访问COMe/Baseboard CPLD : CPLD , LED , WatchDog
// switchboard.c: fpga下i2c访问Switch CPLD1,Switch CPLD2 : CPLD, FPGA , QSFP#include "common_hq.h"
#include
#define CPLD_DRIVER_NAME "sys_cpld"
#define CPLD_DRIVER_VER "0.0.1"
/*** CPLD register address for read and write.*/
/** Base CPLD:0xA100 ~ 0xA1DF* COMe CPLD:0xA1E0 ~ 0xA1FF* */
#define BASE_CPLD_ADDR 0xA100
#define COME_CPLD_ADDR 0xA1E0
#define VERSION_ADDR 0xA100#define BASE_PCB_VER_ADDR 0xA100
#define BASE_H_VER_ADDR 0xA101
#define BASE_M_VER_ADDR 0xA102
#define BASE_L_VER_ADDR 0xA103
#define BASE_SCRATCH_ADDR 0xA104#define COME_PCB_VER_ADDR 0xA1E0
#define COME_H_VER_ADDR 0xA1E1
#define COME_M_VER_ADDR 0xA1E2
#define COME_L_VER_ADDR 0xA1E3
#define COME_SCRATCH_ADDR 0xA1E4#define CPLD_REGISTER_SIZE 0xFF
#define CPLD_TOTAL_NUMBER 4/*watchdog*/
#define BASE_REG_ADDR_WD_EN 0xA190
#define BASE_REG_ADDR_WD_LTIME 0xA191
#define BASE_REG_ADDR_WD_HTIME 0xA192
#define BASE_REG_ADDR_WD_KICK 0xA193
#define BASE_REG_ADDR_WD_FOUN 0xA194
#define BASE_REG_ADDR_WD_STAE 0xA195 //status
#define BASE_REG_ADDR_WD_CLEAR 0xA196
#define BASE_REG_ADDR_WD_LTIMELEFT 0xA197
#define BASE_REG_ADDR_WD_HTIMELEFT 0xA198/*sysled*/
#define PSU_LED_ADDR 0xA140
#define SYS_LED_ADDR 0xA141
#define Alarm_LED_ADDR 0xA142
#define Fan_LED_ADDR 0xA143
#define BMC_LED_ADDR 0xA144enum
{DARK,GREEN,YELLOW,RED,BLUE,GREEN_LIGHT_FLASHING,YELLOW_LIGHT_FLASHING,RED_LIGHT_FLASHING,BLUE_LIGHT_FLASHING
};int set_bit_value(int value,int bit,int status);
int get_bit_value(int value,int bit);/******************************************************watchdog*******************************************************************/
ssize_t get_main_watchdog_identify(char *buf, size_t count)
{return sprintf(buf,"CPU_wdt\n");
}
EXPORT_SYMBOL(get_main_watchdog_identify);ssize_t get_main_watchdog_state(char *buf, size_t count)
{int data=inb(BASE_REG_ADDR_WD_EN);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",BASE_REG_ADDR_WD_EN,inb(BASE_REG_ADDR_WD_EN));data = get_bit_value(data,0);data=sprintf(buf,"%x\n",data); //转为16进制return data;
}
EXPORT_SYMBOL(get_main_watchdog_state);ssize_t get_main_watchdog_timeleft(char *buf, size_t count)
{int data_ligh = inb(BASE_REG_ADDR_WD_HTIMELEFT);// printk(KERN_INFO "Baseboard CPLD addr BASE_REG_ADDR_WD_HTIME :%.2x,value: %.2x \n",BASE_REG_ADDR_WD_HTIMELEFT,data_ligh);int data_low = inb(BASE_REG_ADDR_WD_LTIMELEFT);// printk(KERN_INFO "Baseboard CPLD addr BASE_REG_ADDR_WD_LTIME:%.2x,value: %.2x \n",BASE_REG_ADDR_WD_LTIMELEFT,data_low);int data=(data_ligh << 8 )+data_low;// printk(KERN_INFO "data :%.2x \n",data);data=data/1000;data=sprintf(buf,"%d\n",data);return data;
}
EXPORT_SYMBOL(get_main_watchdog_timeleft);ssize_t get_main_watchdog_timeout(char *buf, size_t count)
{int data_ligh = inb(BASE_REG_ADDR_WD_HTIME);// printk(KERN_INFO "Baseboard CPLD addr BASE_REG_ADDR_WD_HTIME :%.2x,value: %.2x \n",BASE_REG_ADDR_WD_HTIME,data_ligh);int data_low = inb(BASE_REG_ADDR_WD_LTIME);// printk(KERN_INFO "Baseboard CPLD addr BASE_REG_ADDR_WD_LTIME:%.2x,value: %.2x \n",BASE_REG_ADDR_WD_LTIME,data_low);int data=(data_ligh << 8 )+data_low; //拼接// printk(KERN_INFO "data :%.2x \n",data);data=data/1000; //毫秒变成秒data=sprintf(buf,"%d\n",data);return data;
}
EXPORT_SYMBOL(get_main_watchdog_timeout);int set_main_watchdog_timeout(int value)
{int value_ms = value * 1000 ; //秒变成毫秒outb(value_ms&0xff ,BASE_REG_ADDR_WD_LTIME); //outb写,取低八位outb((value_ms>>8)&0xff ,BASE_REG_ADDR_WD_HTIME);return;
}
EXPORT_SYMBOL(set_main_watchdog_timeout);static void feed_watchdog(void)
{int addr,value;addr = BASE_REG_ADDR_WD_KICK;value = inb(addr); // 读value = set_bit_value(value,0,0); // 设 0x7cvalue = set_bit_value(value,1,0);value = set_bit_value(value,2,1);value = set_bit_value(value,3,1);value = set_bit_value(value,4,1);value = set_bit_value(value,5,1);value = set_bit_value(value,6,1);value = set_bit_value(value,7,0);outb(value,addr); // 写
}ssize_t get_main_watchdog_enable_status(char *buf, size_t count)
{int addr,value;addr = BASE_REG_ADDR_WD_EN;value=inb(addr);value = get_bit_value(value,0); //看最后一位return sprintf(buf,"%02X\n", value);
}
EXPORT_SYMBOL(get_main_watchdog_enable_status);int set_main_watchdog_enable_status(int status)
{int addr,value;addr = BASE_REG_ADDR_WD_EN;value = inb(addr);switch(status){case 0:value = set_bit_value(value,0,0);outb(value,addr);break;case 1:value = set_bit_value(value,0,1);outb(value,addr);feed_watchdog();break;default:return -ENOSYS;}return status;
}
EXPORT_SYMBOL(set_main_watchdog_enable_status);/******************************************************************************new enable node***********************************/
ssize_t get_watchdog_enable_status(struct device *dev, struct device_attribute *attr, char *buf)
{size_t count=0;return get_main_watchdog_enable_status(buf, count);
}
static ssize_t set_watchdog_enable_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{int value,rc = 0;rc = kstrtoint(buf,10,&value);if (rc != 0) {return size;}set_main_watchdog_enable_status(value);return size;
}
static struct device_attribute watchdog_enable_attr = __ATTR(enable, S_IRUGO | S_IWUSR,get_watchdog_enable_status,set_watchdog_enable_status);/****************************************************************************new timeout node*******************************/
ssize_t get_watchdog_timeout(struct device *dev, struct device_attribute *attr, char *buf)
{return get_main_watchdog_timeout(buf,NULL);
}
static ssize_t set_watchdog_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{int value,rc = 0;rc = kstrtoint(buf,10,&value);if (rc != 0) {return size;}set_main_watchdog_timeout(value);return size;
}
static struct device_attribute watchdog_timeout_attr = __ATTR(timeout, S_IRUGO | S_IWUSR,get_watchdog_timeout,set_watchdog_timeout);/******************************************************************************new feed node*******************************/
static ssize_t hq_set_watchdog_feed(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{int data,rc = 0;rc = kstrtoint(buf,16,&data);if (rc != 0) {return size;}// printk(KERN_INFO "Baseboard CPLD addr BASE_REG_ADDR_WD_KICK :%.2x,value: %.2x \n",BASE_REG_ADDR_WD_KICK,data);if(data==0x7c){outb(data,BASE_REG_ADDR_WD_KICK);// printk(KERN_INFO "Baseboard CPLD feed dog getreg value : %.2x \n",inb(BASE_REG_ADDR_WD_KICK));}else{return -EINVAL;}return size;
}
static struct device_attribute watchdog_feed_attt = __ATTR(feed, S_IRUGO | S_IWUSR, NULL, hq_set_watchdog_feed);/************************************************************************new strategy node*******************************/
ssize_t hq_get_watchdog_strategy(struct device *dev, struct device_attribute *attr, char *buf)
{return sprintf(buf,"%0.2x\n",inb(BASE_REG_ADDR_WD_FOUN));
}
static ssize_t hq_set_watchdog_strategy(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{int data,rc = 0;rc = kstrtoint(buf,16,&data);if (rc != 0) {return size;}if((data==0x01) || (data ==0x02)){outb(data,BASE_REG_ADDR_WD_FOUN);// printk(KERN_INFO " hq_set_watchdog_strategy addr value : %.2x \n",inb(BASE_REG_ADDR_WD_FOUN));}else{return -EINVAL;}return size;
}
static struct device_attribute watchdog_strategy_attr = __ATTR(strategy, S_IRUGO | S_IWUSR,hq_get_watchdog_strategy ,hq_set_watchdog_strategy);/********************************************************************new timeout_counts node*******************************/
ssize_t hq_get_watchdog_timeout_times(struct device *dev, struct device_attribute *attr, char *buf)
{return sprintf(buf,"%d\n",inb(BASE_REG_ADDR_WD_STAE));
}
static struct device_attribute watchdog_timeout_counts_attr = __ATTR(timeout_counts, S_IWUSR|S_IRUGO,hq_get_watchdog_timeout_times, NULL);/********************************************************************new timeout_reset node*******************************/
static ssize_t hq_set_watchdog_timeout_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{int data,rc = 0;rc = kstrtoint(buf,16,&data);if (rc != 0) {return size;}if(data==1){outb(data,BASE_REG_ADDR_WD_KICK);}else{return -EINVAL;}return size;
}
static struct device_attribute watchdog_timeout_reset_attr = __ATTR(timeout_reset, S_IRUGO | S_IWUSR,NULL ,hq_set_watchdog_timeout_reset);static struct attribute *watchdog_dir_attrs[] = {&watchdog_enable_attr.attr,&watchdog_timeout_attr.attr,&watchdog_feed_attt.attr,&watchdog_strategy_attr.attr,&watchdog_timeout_counts_attr.attr,&watchdog_timeout_reset_attr.attr,NULL
};static struct attribute_group watchdog_attr_group = { // 在下面cpld_hq_drv_probe函数里: kobject_create_and_add, sysfs_create_group.attrs = watchdog_dir_attrs,
};
/******************************************************watchdog end*********************************************************************************//******************************************************sysled begain*******************************************************************************/
int set_sysled_state(int status,char *names)
{int addr,value;if(strcmp(names,"PSU")==0){addr=PSU_LED_ADDR;}else if(strcmp(names,"SYS")==0){addr=SYS_LED_ADDR;}else if(strcmp(names,"Alarm")==0){addr=Alarm_LED_ADDR;}else if(strcmp(names,"Fan")==0){addr=Fan_LED_ADDR;}else if(strcmp(names,"BMC")==0){addr=BMC_LED_ADDR;}else{return -ENOSYS;}value=inb(addr);switch(status){case DARK:value=set_bit_value(value,6,1);value=set_bit_value(value,0,1);value=set_bit_value(value,1,0);outb(value,addr);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",addr,inb(addr));break;case GREEN:value=set_bit_value(value,6,1);value=set_bit_value(value,4,0);value=set_bit_value(value,5,0);value=set_bit_value(value,1,0);value=set_bit_value(value,0,0);outb(value,addr);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",addr,inb(addr));break;case YELLOW:value=set_bit_value(value,6,1);value=set_bit_value(value,4,1);value=set_bit_value(value,5,0);value=set_bit_value(value,1,0);value=set_bit_value(value,0,0);outb(value,addr);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",addr,inb(addr));break; case RED:return -ENOSYS;case BLUE:return -ENOSYS;case GREEN_LIGHT_FLASHING:value=set_bit_value(value,6,1);value=set_bit_value(value,4,0);value=set_bit_value(value,5,0);value=set_bit_value(value,1,1);value=set_bit_value(value,0,0);outb(value,addr);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",addr,inb(addr));break;case YELLOW_LIGHT_FLASHING:value=set_bit_value(value,6,1);value=set_bit_value(value,4,1);value=set_bit_value(value,5,0);value=set_bit_value(value,1,1);value=set_bit_value(value,0,0);outb(value,addr);// printk(KERN_INFO "Baseboard CPLD addr:%.2x ,value: %.2x \n",addr,inb(addr));break;case RED_LIGHT_FLASHING:return -ENOSYS;case BLUE_LIGHT_FLASHING:return -ENOSYS;default:return -ENOSYS;}return 1;
}
EXPORT_SYMBOL(set_sysled_state);ssize_t get_sysled_state(char *buf, size_t count,char *names)
{int addr,value;int len=-1;if(strcmp(names,"PSU")==0){addr=PSU_LED_ADDR;}else if(strcmp(names,"SYS")==0){addr=SYS_LED_ADDR;}else if(strcmp(names,"Alarm")==0){addr=Alarm_LED_ADDR;}else if(strcmp(names,"Fan")==0){addr=Fan_LED_ADDR;}else if(strcmp(names,"BMC")==0){addr=BMC_LED_ADDR;}else{return -ENOSYS;}value=inb(addr);if(get_bit_value(value,0)==1 && get_bit_value(value,1)==0){len=sprintf(buf,"dark\n");return len;}else if(get_bit_value(value,0)==0 && get_bit_value(value,1)==0){//buf chang liang 常亮if(get_bit_value(value,4)==0 && get_bit_value(value,5)==0){len=sprintf(buf,"green\n");return len;}else if(get_bit_value(value,4)==1 && get_bit_value(value,5)==0){len=sprintf(buf,"yellow\n");return len;}else{;}}else if(get_bit_value(value,0)==0 && get_bit_value(value,1)==1){//buf 闪烁if(get_bit_value(value,4)==0 && get_bit_value(value,5)==0){len=sprintf(buf,"green light flashing\n");return len;}else if(get_bit_value(value,4)==1 && get_bit_value(value,5)==0){len=sprintf(buf,"yellow light flashing\n");return len;}else{;}}else{return -ENOSYS;}
}
EXPORT_SYMBOL(get_sysled_state);int get_bit_value(int value,int bit)
{if(value<0 || value>0xff || bit<0 || bit>7){return -1;}int data ;data=value >> bit & 0x01; // 右移bit位并取最后一位return data;
}int set_bit_value(int value,int bit,int status)
{if(value<0 || value>0xff || bit<0 || bit>7|| status<0 || status>1){return -1;}else{if(status==0) //将1111 1111第二位(从0开始即第三位)置为0{value=(~(1<value = (1<;}}
}
/*****************************************************sysled end*************************************************************************************//***********************************************CPLD begain*******************************************************************************************/
int get_board_cpld_number(void)
{/* add vendor codes here */return CPLD_TOTAL_NUMBER;
}
EXPORT_SYMBOL(get_board_cpld_number);/** demo_get_main_board_cpld_alias - Used to identify the location of cpld,* @cpld_index: start with 1* @buf: Data receiving buffer* @count: length of buf** This function returns the length of the filled buffer,* if not support this attributes filled "NA" to buf,* otherwise it returns a negative value on failed.*/
ssize_t get_board_cpld_alias(unsigned int cpld_index, char *buf, size_t count)
{/* add vendor codes here */int len = -1 ;switch(cpld_index){case 1 :len=sprintf(buf,"Base board CPLD\n");break ;case 2 :len=sprintf(buf,"Come CPLD\n");break ;default:len = -1 ;break;}return len;
}
EXPORT_SYMBOL(get_board_cpld_alias);/** demo_get_main_board_cpld_type - Used to get cpld model name* @cpld_index: start with 1* @buf: Data receiving buffer* @count: length of buf** This function returns the length of the filled buffer,* if not support this attributes filled "NA" to buf,* otherwise it returns a negative value on failed.*/
ssize_t get_board_cpld_type(unsigned int cpld_index, char *buf, size_t count)
{/* add vendor codes here */int len = -1 ;switch(cpld_index){case 1 :len=sprintf(buf,"LCMXO3LF-4300C-5BG400C CPLD\n");break ;case 2 :len=sprintf(buf,"LCMXO3LF-2100C-5BG400C CPLD\n");break ;default:len = -1 ;break;}return len;
}
EXPORT_SYMBOL(get_board_cpld_type);/** demo_get_main_board_cpld_firmware_version - Used to get cpld firmware version,* @cpld_index: start with 1* @buf: Data receiving buffer* @count: length of buf** This function returns the length of the filled buffer,* if not support this attributes filled "NA" to buf,* otherwise it returns a negative value on failed.*/
ssize_t get_board_cpld_firmware_version(unsigned int cpld_index, char *buf, size_t count)
{/* add vendor codes here */int len = -1; switch(cpld_index){case 1:printk(KERN_INFO "BASE CPLD H version:0x%2.2x\n", inb(BASE_H_VER_ADDR));printk(KERN_INFO "BASE CPLD M version:0x%2.2x\n", inb(BASE_M_VER_ADDR));printk(KERN_INFO "BASE CPLD L version:0x%2.2x\n", inb(BASE_L_VER_ADDR)); len = sprintf(buf,"%x.%x.%x\n", inb(BASE_H_VER_ADDR),inb(BASE_M_VER_ADDR),inb(BASE_L_VER_ADDR));break;case 2:printk(KERN_INFO "COME CPLD H version:0x%2.2x\n", inb(COME_H_VER_ADDR));printk(KERN_INFO "COME CPLD M version:0x%2.2x\n", inb(COME_M_VER_ADDR));printk(KERN_INFO "COME CPLD L version:0x%2.2x\n", inb(COME_L_VER_ADDR));len = sprintf(buf,"%x.%x.%x\n", inb(COME_H_VER_ADDR),inb(COME_M_VER_ADDR),inb(COME_L_VER_ADDR)); break;default:len = -1;break;}return len;
}
EXPORT_SYMBOL(get_board_cpld_firmware_version);/** demo_get_main_board_cpld_board_version - Used to get cpld board version,* @cpld_index: start with 1* @buf: Data receiving buffer* @count: length of buf** This function returns the length of the filled buffer,* if not support this attributes filled "NA" to buf,* otherwise it returns a negative value on failed.*/
ssize_t get_board_cpld_board_version(unsigned int cpld_index, char *buf, size_t count)
{/* add vendor codes here */int len = -1; switch(cpld_index){case 1:len = sprintf(buf,"%02X\n", inb(BASE_PCB_VER_ADDR));break;case 2:len = sprintf(buf,"%02X\n", inb(COME_PCB_VER_ADDR));break;default:len = -1;break;}return len;
}
EXPORT_SYMBOL(get_board_cpld_board_version);/** demo_get_main_board_cpld_test_reg - Used to test cpld register read* filled the value to buf, value is hexadecimal, start with 0x* @cpld_index: start with 1* @buf: Data receiving buffer* @count: length of buf** This function returns the length of the filled buffer,* if not support this attributes filled "NA" to buf,* otherwise it returns a negative value on failed.*/
ssize_t get_board_cpld_test_reg(unsigned int cpld_index, char *buf, size_t count)
{/* add vendor codes here */int len = -1 ;switch(cpld_index){case 1 :len=sprintf(buf,"%02x\n",inb(BASE_SCRATCH_ADDR));break ;case 2 :len=sprintf(buf,"%02x\n",inb(COME_SCRATCH_ADDR));break ;default:len = -1 ;break;}return len;
}
EXPORT_SYMBOL(get_board_cpld_test_reg);/** demo_set_main_board_cpld_test_reg - Used to test cpld register write* @cpld_index: start with 1* @value: value write to cpld** This function returns 0 on success,* otherwise it returns a negative value on failed.*/
int set_board_cpld_test_reg(unsigned int cpld_index, unsigned int value)
{/* add vendor codes here */int ret = -1 ;switch(cpld_index){case 1 :outb(value,BASE_SCRATCH_ADDR);ret = 1;break ;case 2 :outb(value,COME_SCRATCH_ADDR);ret = 1;break ;default: ret = -1 ;break;}return ret;
}
EXPORT_SYMBOL(set_board_cpld_test_reg);
/********************************************************CPLD end***********************************************************************/struct cpld_hq_data {struct mutex cpld_lock;uint16_t read_addr;uint16_t base_addr;
};struct cpld_hq_data *cpld_data;static ssize_t get_cpld_reg_address(struct device *dev, struct device_attribute *attr, char *buf)
{int len = 0;// CPLD register is one bytemutex_lock(&cpld_data->cpld_lock);len = sprintf(buf, "0x%2.2x\n",inb(cpld_data->read_addr));mutex_unlock(&cpld_data->cpld_lock);return len;
}/*** Store the register address* @param buf address wanted to be read value of* @return number of bytes stored, or an error code*/
static ssize_t set_cpld_reg_address(struct device *dev, struct device_attribute *devattr,const char *buf, size_t count)
{uint32_t addr;char *last;mutex_lock(&cpld_data->cpld_lock);addr = (uint32_t)strtoul(buf, &last, 16);if (addr == 0 && buf == last) {return -EINVAL;}cpld_data->read_addr = cpld_data->base_addr + addr;mutex_unlock(&cpld_data->cpld_lock);return count;
}static DEVICE_ATTR( getreg, 0600, get_cpld_reg_address, set_cpld_reg_address);static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr,const char *buf, size_t count)
{// CPLD register is one byteuint16_t addr;uint8_t value;char *tok;char clone[count+1];char *pclone = clone;char *last;strcpy(clone, buf);mutex_lock(&cpld_data->cpld_lock);tok = strsep((char**)&pclone, " ");if(tok == NULL){mutex_unlock(&cpld_data->cpld_lock);return -EINVAL;}addr = (uint16_t)strtoul(tok, &last,16);if(addr == 0 && tok == last){mutex_unlock(&cpld_data->cpld_lock);return -EINVAL;}tok = strsep((char**)&pclone, " ");if(tok == NULL){mutex_unlock(&cpld_data->cpld_lock);return -EINVAL;}value = (uint8_t)strtoul(tok, &last,16);if(value == 0 && tok == last){mutex_unlock(&cpld_data->cpld_lock);return -EINVAL;}outb(value, cpld_data->base_addr + addr);mutex_unlock(&cpld_data->cpld_lock);return count;
}
//static DEVICE_ATTR_WO(setreg);
static DEVICE_ATTR( setreg, 0200, NULL , setreg_store);
/*** Read all CPLD register in binary mode.* @return number of byte read.*/
static ssize_t dump_read(struct file *filp, struct kobject *kobj,struct bin_attribute *attr, char *buf,loff_t off, size_t count)
{unsigned long i = 0;ssize_t status;mutex_lock(&cpld_data->cpld_lock);begin:if(i < count){buf[i++] = inb(VERSION_ADDR + off);off++;msleep(1);goto begin;}status = count;exit:mutex_unlock(&cpld_data->cpld_lock);return status;
}static BIN_ATTR_RO(dump, CPLD_REGISTER_SIZE);static struct attribute *cpld_hq_attrs[] = {&dev_attr_getreg.attr,&dev_attr_setreg.attr,NULL,
};static struct bin_attribute *cpld_hq_bin_attrs[] = {&bin_attr_dump,NULL,
};static struct attribute_group cpld_hq_attrs_group = {.attrs = cpld_hq_attrs,.bin_attrs = cpld_hq_bin_attrs,
};static struct resource cpld_hq_resources[] = {{.start = 0xA100,.end = 0xA1FF,.flags = IORESOURCE_IO,},
};static void cpld_hq_dev_release( struct device * dev)
{return;
}static struct platform_device cpld_hq_dev = {.name = CPLD_DRIVER_NAME,.id = -1,.num_resources = ARRAY_SIZE(cpld_hq_resources),.resource = cpld_hq_resources,.dev = {.release = cpld_hq_dev_release,}
};static int cpld_hq_drv_remove(struct platform_device *pdev)
{sysfs_remove_group(&pdev->dev.kobj, &cpld_hq_attrs_group);return 0;
}static struct kobject *watchdog = NULL;
static int cpld_hq_drv_probe(struct platform_device *pdev)
{struct resource *resource;int err = 0;cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_hq_data), GFP_KERNEL);if(!cpld_data)return -ENOMEM;mutex_init(&cpld_data->cpld_lock);cpld_data ->read_addr = VERSION_ADDR;cpld_data ->base_addr = BASE_CPLD_ADDR;resource = platform_get_resource(pdev, IORESOURCE_IO, 0);if(unlikely(!resource)){printk(KERN_ERR "Specified Resource Not Available...\n");return -ENODEV;}err = sysfs_create_group(&pdev->dev.kobj, &cpld_hq_attrs_group);if(err) {printk(KERN_ERR "Cannot create sysfs for system CPLD\n");return err;}printk(KERN_INFO "CPLD Probe driver");printk(KERN_INFO "BASE CPLD Address:ox%2.2x\n", BASE_CPLD_ADDR);printk(KERN_INFO "COMe CPLD Address:ox%2.2x\n", COME_CPLD_ADDR);printk(KERN_INFO "BASE CPLD PCB version:0x%2.2x\n", inb(BASE_PCB_VER_ADDR));printk(KERN_INFO "BASE CPLD H version:0x%2.2x\n", inb(BASE_H_VER_ADDR));printk(KERN_INFO "BASE CPLD M version:0x%2.2x\n", inb(BASE_M_VER_ADDR));printk(KERN_INFO "BASE CPLD L version:0x%2.2x\n", inb(BASE_L_VER_ADDR));printk(KERN_INFO "COME CPLD PCB version:0x%2.2x\n", inb(COME_PCB_VER_ADDR));printk(KERN_INFO "COME CPLD H version:0x%2.2x\n", inb(COME_H_VER_ADDR));printk(KERN_INFO "COME CPLD M version:0x%2.2x\n", inb(COME_M_VER_ADDR));printk(KERN_INFO "COME CPLD L version:0x%2.2x\n", inb(COME_L_VER_ADDR)); printk(KERN_INFO "GPIO base address:0x%x\n", inl(0x48));//watchdogwatchdog = kobject_create_and_add("watchdog",&pdev->dev.kobj);if (!watchdog){return -ENOMEM;}if(sysfs_create_group(watchdog,&watchdog_attr_group)){printk(KERN_INFO"watchdog_attr_group failed\n");return -1;}/*int ret;ret=watchdog_root_create();if (ret < 0) {WDT_ERR("watchdog create error.\n");return ret;}*/return 0;}static struct platform_driver cpld_hq_drv = {.probe = cpld_hq_drv_probe,.remove = __exit_p(cpld_hq_drv_remove),.driver = {.name = CPLD_DRIVER_NAME,},
};static int __init cpld_hq_init(void)
{/*Register Platform device and Platform Driver*/platform_device_register(&cpld_hq_dev);platform_driver_register(&cpld_hq_drv);printk(KERN_INFO "%s: version %s loaded successfully\n", CPLD_DRIVER_NAME, CPLD_DRIVER_VER);return 0;
}static void __exit cpld_hq_exit(void)
{/*Unregister Platform device and Platform Driver*/platform_driver_unregister(&cpld_hq_drv);platform_device_unregister(&cpld_hq_dev);printk(KERN_INFO "%s: unloaded successfully\n", CPLD_DRIVER_NAME);
}module_init(cpld_hq_init);
module_exit(cpld_hq_exit);MODULE_AUTHOR("Huaqin Technology Co.,Ltd.");
MODULE_DESCRIPTION("Hua Qin Common CPLD");
MODULE_VERSION(CPLD_DRIVER_VER);
MODULE_LICENSE("GPL");
// i2c-ocores.c
struct ocores_i2c {int prescale; //属性
};static ssize_t i2c_clk_show(struct device *dev, struct device_attribute *attr, char *buf)
{struct ocores_i2c *i2c_test = dev_get_drvdata(dev);if(i2c_test->prescale==0xe0){return sprintf(buf,"100\n");}else if(i2c_test->prescale==0x71){return sprintf(buf,"200\n");}else if(i2c_test->prescale==0x36){return sprintf(buf,"400\n");}else{return sprintf(buf,"please echo 100/200/400 hz bus clk \n");}
}static ssize_t i2c_clk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{ssize_t status;int value;struct ocores_i2c *i2c_test = dev_get_drvdata(dev);i2c_test->prescale=0xe6;u8 ctrl = oc_getreg(i2c_test, OCI2C_CONTROL);// printk(KERN_INFO "into set \n");status = kstrtoint(buf,10,&value);if(value==100){i2c_test->prescale=0xe0;// dev_info(dev, "----------------------------100-------------------------\n");}else if(value==200){i2c_test->prescale=0x71;// dev_info(dev, "----------------------------200-------------------------\n");}else if(value==400){i2c_test->prescale=0x36;// dev_info(dev, "----------------------------400-------------------------\n");}else{dev_info(dev, "This I2C bus frequency cannot be provided\n");return -EINVAL;}//printk(KERN_INFO "out if code \n");oc_setreg(i2c_test, OCI2C_PRELOW, i2c_test->prescale & 0xff);oc_setreg(i2c_test, OCI2C_PREHIGH, i2c_test->prescale >> 8);oc_setreg(i2c_test, OCI2C_CMD, OCI2C_CMD_IACK); /* Init the device */oc_setreg(i2c_test, OCI2C_CONTROL, ctrl | OCI2C_CTRL_EN);u8 data = oc_getreg(i2c_test,OCI2C_PRELOW);printk(KERN_INFO "OCI2C_PRELOW: %x\n",data);u8 data1 =oc_getreg(i2c_test,OCI2C_PREHIGH);printk(KERN_INFO "OCI2C_PREHIGH: %x\n",data1);u8 data2 = oc_getreg(i2c_test,OCI2C_CMD);printk(KERN_INFO "OCI2C_CMD: %x\n",data2);u8 data3 =oc_getreg(i2c_test,OCI2C_CONTROL);printk(KERN_INFO "OCI2C_CONTROL: %x\n",data3);// dev_info(dev, "Address: %lx\n", i2c_test->base);// dev_info(dev, "Prescale: %d\n", i2c_test->prescale);// printk(KERN_INFO " end \n");return size;
}
struct device_attribute i2c_ocores_test = __ATTR(i2c_bus_freq, 0600, i2c_clk_show,i2c_clk_store);static struct attribute *i2c_ocores_dttrs[] = {&i2c_ocores_test.attr,NULL,
};static struct attribute_group ocores_attr_test = { // ocores_attr_test 在ocores_i2c_probe函数里即845行添加节点.attrs = i2c_ocores_dttrs ,
};static void i2c_ocores_dev_release(struct device * dev)
{return;
}/******************create /sys/bus/platform/device/ocores-i2c-hq.1***********************/
static struct platform_device i2c_ocores_dev = {.name = "ocores-i2c-hq",.id = -1,.num_resources = 0,.dev = {.release = i2c_ocores_dev_release,}
};static int ocores_i2c_probe(struct platform_device *pdev)
{struct ocores_i2c_platform_data *pdata;struct resource *res;struct ocores_i2c *i2c_test;int irq;int ret;int i;i2c_test = devm_kzalloc(&pdev->dev, sizeof(*i2c_test), GFP_KERNEL);if (!i2c_test)return -ENOMEM;dev_set_drvdata(&pdev->dev, i2c_test); //spin_lock_init(&i2c_test->process_lock);res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (res) {i2c_test->base = devm_ioremap_resource(&pdev->dev, res);printk(KERN_INFO "---------------------------------------------ocore Address-------------------------------: %lx\n", i2c_test->base);// dev_info(pdev,"ocore Address: %lx\n", i2c_test->base);if (IS_ERR(i2c_test->base))return PTR_ERR(i2c_test->base);/*******************************************create i2c_bus_freq****************************************/int err = 0;err = sysfs_create_group(&pdev->dev.kobj,&ocores_attr_test); if(err){printk(KERN_ERR "Cannot create sysfs for system I2C\n");return err;}return 0;err_clk:clk_disable_unprepare(i2c_test->clk);return ret;
}
s3ip_sysfs_tool.sh#! /bin/bash
s3ip_link_hq(){sudo rm -rf /usr/local/s3ip/sudo mkdir /usr/local/s3ipln -s /sys/bus/i2c/devices/i2c-0/0-0056/eeprom /usr/local/s3ip/syseeprommkdir /usr/local/s3ip/transceiverfor((i=1;i<=32;i++));domkdir /usr/local/s3ip/transceiver/eth$i# /sys_switch (s3ip_load.py和.json) 软连接到 /usr/local 再软连接到 /sys/s3ipln -s /sys/bus/i2c/devices/$((36+i))-0050/eeprom /usr/local/s3ip/transceiver/eth$i/eepromln -s /sys/s3ip/transceiver/eth$i/interrupt /usr/local/s3ip/transceiver/eth$i/interruptln -s /sys/s3ip/transceiver/eth$i/power_on /usr/local/s3ip/transceiver/eth$i/power_onln -s /sys/s3ip/transceiver/eth$i/reset /usr/local/s3ip/transceiver/eth$i/resetln -s /sys/s3ip/transceiver/eth$i/tx_disable /usr/local/s3ip/transceiver/eth$i/tx_disableln -s /sys/s3ip/transceiver/eth$i/low_power_mode /usr/local/s3ip/transceiver/eth$i/low_power_modeln -s /sys/s3ip/transceiver/eth$i/present /usr/local/s3ip/transceiver/eth$i/presentln -s /sys/s3ip/transceiver/eth$i/rx_los /usr/local/s3ip/transceiver/eth$i/rx_losln -s /sys/s3ip/transceiver/eth$i/tx_fault //usr/local/s3ip/transceiver/eth$i/tx_faultdone
}s3ip_start(){sudo insmod /lib/modules/s3ip/s3ip_sysfs.kosudo insmod /lib/modules/s3ip/syseeprom_device_driver.kosudo insmod /lib/modules/s3ip/fan_device_driver.kosudo insmod /lib/modules/s3ip/cpld_device_driver.kosudo insmod /lib/modules/s3ip/sysled_device_driver.kosudo insmod /lib/modules/s3ip/psu_device_driver.kosudo insmod /lib/modules/s3ip/transceiver_device_driver.kosudo insmod /lib/modules/s3ip/temp_sensor_device_driver.kosudo insmod /lib/modules/s3ip/vol_sensor_device_driver.kosudo insmod /lib/modules/s3ip/fpga_device_driver.kosudo insmod /lib/modules/s3ip/watchdog_device_driver.kosudo insmod /lib/modules/s3ip/curr_sensor_device_driver.kosudo insmod /lib/modules/s3ip/slot_device_driver.kos3ip_link_hqsudo rm -rf /sys_switchsudo /usr/bin/s3ip_load.pyecho "s3ip service start"
}
s3ip_stop(){sudo rmmod slot_device_driversudo rmmod curr_sensor_device_driversudo rmmod watchdog_device_driversudo rmmod fpga_device_driversudo rmmod vol_sensor_device_driversudo rmmod temp_sensor_device_driversudo rmmod transceiver_device_driversudo rmmod psu_device_driversudo rmmod sysled_device_driversudo rmmod cpld_device_driversudo rmmod fan_device_driversudo rmmod syseeprom_device_driversudo rmmod s3ip_sysfssudo rm -rf /sys_switchecho "s3ip service stop"}case "$1" instart)s3ip_start;;stop)s3ip_stop;;status)sudo tree -l /sys_switch;;restart)s3ip_stops3ip_start;; *)echo "Usage: $0 {start|stop|status|restart}"exit 1
esac
exit

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/binWATCHDOG_LOG="/tmp/watchdog.log"usage(){program=$(basename "$0")echo "Usage:"echo "$program "echo " : start stop kick query restart"echo "Examples:"echo " $program start"echo ""
}kick()
{ret=$(head -1 /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenecho "0x7c" > /sys/bus/i2c/devices/0-000d/wd_kickelseusageexitfiret=$(date)echo "$ret ${FUNCNAME[0]}" >> $WATCHDOG_LOG
}enable()
{ret=$(head -1 /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" != "0x1" ];thenecho "0x1" > /sys/bus/i2c/devices/0-000d/wd_enelseusageexitfiret=$(date)echo "$ret ${FUNCNAME[0]}" > $WATCHDOG_LOG
}disable()
{ret=$(head -1 /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenecho "0x0" > /sys/bus/i2c/devices/0-000d/wd_enecho "0x7c" > /sys/bus/i2c/devices/0-000d/wd_kickelseusageexitfiret=$(date)echo "$ret ${FUNCNAME[0]}" >> $WATCHDOG_LOG
}check_parameter()
{if [ $# -ne 1 ];thenusageexitficase ${1} in"start" | "stop" | "kick" |"query" |"restart");;*) #除上面的其他的usageexit;;esac
}check_parameter "$@"case ${1} in"start")ret=$(head -1 /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenusageexitfienablekick;;"stop")disableexit;;"kick")kickexit;;"restart")ret=$(head -1 /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenusageexitfienablekickexit;;"query")ret=$(head -1 /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenecho "ENABLE"elseecho "DISABLE"fiexit;;
esacwhile true
doret=$(head -1 /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenkickfisleep 30
done
root@bmc-oob:~# ps | grep wd588 root 2904 S runsv /etc/sv/wd591 root 3036 S {wd} /bin/bash /usr/local/bin/wd start779 root 3036 S grep wd
root@bmc-oob:~# wd query
ENABLE
root@bmc-oob:~# wd stop
root@bmc-oob:~# wd query
DISABLE
root@bmc-oob:~# wd restart
root@bmc-oob:~# wd kick
root@bmc-oob:~# wd query
ENABLE
init()
{ret=$(ps |grep crond|grep -v grep)if [ "x$ret" = "x" ];thenecho "No found crond process"exitfiif [ ! -d /crontabs ];thenmkdir /crontabstouch /crontabs/rootficrontab -c /etc/cron/crontabs/ /etc/cron/crontabs/rootcp /var/log/watchdog.sh /usr/local/bin/watchdog.sh
}add_task()
{echo "* * * * * /usr/local/bin/watchdog.sh kick" >> /etc/cron/crontabs/rootecho "* * * * * date >> /var/log/date.log" >> /etc/cron/crontabs/root
}del_task()
{sed -i "/\* \* \* \* \* \/usr\/local\/bin\/watchdog.sh kick/d" /etc/cron/crontabs/root
}

如下0x100代表default flash。







如下202第1位(不是第0位)和第9位置为1,发现这时确实WDT2可控,当前在备flash启动。












wdt1和wdt2都切到备flash。

如下clear寄存器清除wdt1的status,保留了reset次数,但是将code source(主备)清除为0(主)。

再用wdt2切换主。

这次切到了主。

用wdt1切换到备。

清空wdt1的status。这时如果用我们的测试脚本bootsource会判断是在主,其实是在备。

尝试wdt1用0x13切换主,成功切到主。


从备切到主,需要满足两(三)个wdt中都从备切到主。比如wdt1是备,wdt2是备,那要对wdt1,wdt2都下一次0x93。如果wdt1,wdt2中一个是备,那对对应的wdt下0x93。
还有因为清空寄存器造成的虽然在备,但是wdt都是显示在主,这时候用0x13就可以切到主。用wdt2进行切换主备。避免使用清空寄存器0x14/0x34。
a=0x00000100 #256
b=$(( ((a & 0xff00) >> 8 ) ))
c=$((a & 0xff00))
d=$((a >> 8))
echo $b
echo $c
echo $d
# yutao@obmc-server:~/bak$ ./a.sh
# 1
# 256
# 1# 检查当前BMC是在主还是备启动的检查函数boot_source实现如下:
check_boot_source()
{# Please refer to reg WDT1/WDT2 Control Register definition to# understand this code block, WDT1 is on page 646 of ast2500v16.pdf# and WDT2 is on page 649 of ast2500v16.pdf# get watch dog1 timeout status registerwdt1=$(devmem 0x1e785010)# get watch dog2 timeout status registerwdt2=$(devmem 0x1e785030)wdt1_timeout_cnt=$(( ((wdt1 & 0xff00) >> 8) )) #取出高8位,自动转为十进制wdt2_timeout_cnt=$(( ((wdt2 & 0xff00) >> 8) ))wdt1_boot_code_source=$(( ((wdt1 & 0x2) >> 1) )) #取出第1位(不是第0)wdt2_boot_code_source=$(( ((wdt2 & 0x2) >> 1) ))boot_code_source=0# Check both WDT1 and WDT2 to indicate the boot sourceif [ $wdt1_timeout_cnt -ge 1 ] && [ $wdt1_boot_code_source -eq 1 ]; thenboot_code_source=1elif [ $wdt2_timeout_cnt -ge 1 ] && [ $wdt2_boot_code_source -eq 1 ]; thenboot_code_source=1fiecho $boot_code_source
}bmc_boot_info() {wdt1=$(devmem 0x1e785010)wdt2=$(devmem 0x1e785030)wdt1_timeout_cnt=$(( ((wdt1 & 0xff00) >> 8) ))wdt2_timeout_cnt=$(( ((wdt2 & 0xff00) >> 8) ))boot_code_source=$(check_boot_source)boot_source="Master Flash"if [ $((boot_code_source)) -eq 1 ]; thenboot_source="Slave Flash"fiecho "WDT1 Timeout Count: " $wdt1_timeout_cntecho "WDT2 Timeout Count: " $wdt2_timeout_cntecho "Current BMC Boot Code Source: $boot_source"
}bmc_boot_from() {# Enable watchdog reset_system_after_timeout bit and WDT_enable_signal bit.# Refer to ast2500v16.pdf page 650th.boot_source=0x00000013boot_code_source=$(check_boot_source)if [ "$1" = "master" ]; thenif [ $((boot_code_source)) -eq 0 ]; thenecho "Current boot source is master, no need to switch."return 0fi# Set bit_7 to 0 : Use default boot code whenever WDT reset.boot_source=0x00000033elif [ "$1" = "slave" ]; thenif [ $((boot_code_source)) -eq 1 ]; thenecho "Current boot source is slave, no need to switch."return 0fi# No matter BMC boot from any one of master and slave.# Set bit_7 to 1 : Use second boot code whenever WDT reset.# And the sencond boot code stands for the other boot source.boot_source=0x000000b3fiecho "BMC will switch to $1 after 10 seconds..."/usr/local/bin/watch-dog stop# Clear WDT1 counter and boot code source statusdevmem 0x1e785014 w 0x77# Clear WDT2 counter and boot code source statusdevmem 0x1e785034 w 0x77# Set WDT time out 10s, 0x00989680 = 10,000,000 usdevmem 0x1e785024 32 0x00989680# WDT magic number to restart WDT counter to decrease.devmem 0x1e785028 32 0x4755devmem 0x1e78502c 32 $boot_source
}
bmc喂狗gpio硬件管脚:


bmc监听gpio中断硬件管脚:







导出GPIO:echo $gpio_num > /sys/class/gpio/exporteg: echo 1 > /sys/class/gpio/export执行完以上命令后,如果该gpio接口存在且未被占用则会出现如下目录:/sys/class/gpio/gpio1设置方向:gpio的方向分为两类:in和outin:表示该gpio用于输入。(如该gpio连接一个按钮)out:表示该gpio用于输出。(如该gpio连接一个led灯)指定为in模式的命令:echo in > /sys/class/gpio/gpio1/direction指定为out模式的命令如下:echo out > /sys/class/gpio/gpio1/direction //默认value为0echo low > /sys/class/gpio/gpio1/direction //指定方向为out且value为0echo high > /sys/class/gpio/gpio1/direction //指定方向为out且value为1设置高低:只用当方向为out模式时才能指定gpio接口的电压的高低。这个很容易理解,因为如果是in模式的话,它的电平高低取决于所连接外设的电平高低,我们只能读取它的值,不能更改它的值echo 1 > /sys/class/gpio/gpio1/value //指定gpio1为高电平echo 0 > /sys/class/gpio/gpio1/value //指定gpio1为低电平



#ifndef SENSOR_MON__h
#define SENSOR_MON__h#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include //#define GPIO_KICK_NUM 885
//#define GPIO_KICK_NAME "GPIOL5"
#define WDT_MASK_PATH "/sys/bus/i2c/devices/82-000d/bmc_wdt_mask"
#define GPIO_KICK_SHADOW "BMC_CPLD_GPIO69_WDO"typedef enum {WD_FUNC_START, //0WD_FUNC_STOP,WD_FUNC_KICK,WD_FUNC_UNKNOWN,
} wd_func;typedef enum {MASK_ENABLE = 1,MASK_DISABLE = 0,
} wd_mask;// 如下LOG替换syslog , syslog像printf定义在, 打印在/var/log/message
#define LOG(mode,format, ...) syslog(mode, format, __VA_ARGS__)int bmc_wd_set(wd_mask value);
void feed_dog_func();#endif
#include "watch-dog.h"int bmc_wd_set(wd_mask value){ // bmc设置cpld寄存器控制wtd芯片(是外置芯片,不是bmc芯片内置的)开关FILE* pFile = fopen(WDT_MASK_PATH, "w");char regvalue[4]= {0};int ret = 0;if(value == MASK_DISABLE){ // 0sprintf(regvalue,"0x0");}else if(value == MASK_ENABLE){sprintf(regvalue,"0x1");}ret = fwrite(regvalue, sizeof(regvalue) , 1, pFile ); //ret为次数即fwrite中的1if(ret==1){fflush(pFile);ret = 0;}else{ret = -1;}fclose(pFile);return ret;
}void feed_dog_func() // bmc通过gpio的0.5s高低电平来喂狗
{int ret = 0;struct timespec n_sleep;n_sleep.tv_sec = 0; //secondes, integer part sleep duration // 整数n_sleep.tv_nsec = 5e8L; //nanoseconds, decimal part sleep duration // 小数 0.5s(上行整数0,这行小数5)gpio_desc_t* desc = gpio_open_by_shadow(GPIO_KICK_SHADOW); // libgpio-ctrl.so中的接口if (!desc) {syslog(LOG_INFO ,"gpio_open_by_shadow fail\n");return ;}ret = gpio_set_direction(desc, GPIO_DIRECTION_OUT);if (ret == -1){syslog(LOG_ERR ,"gpio_change_direction err \n");gpio_close(desc);return ;}ret = gpio_set_edge(desc, GPIO_EDGE_NONE);if (ret == -1){syslog(LOG_ERR ,"gpio_change_edge err \n");gpio_close(desc);return ;}
//BMC启动时,喂狗(硬件gpio管脚,每隔500ms翻转一次高低电平),并关闭中断MASK如下:
//cmm cpld 0X71 地址 bit0 是中断MASK (为1时MASK使能即看门狗关闭;为0时MASK失效即看门狗打开)
//i2cset -f -y 82 0xd 0x71 0xfe 做成bmc_wdt_mask节点ret=bmc_wd_set(MASK_DISABLE); // 0开wtdif(ret == 0){syslog(LOG_INFO ,"bmc_wd_set OK\n");}else{syslog(LOG_ERR ,"bmc_wd_set Fail\n");gpio_close(desc);return;}while(1){gpio_set_value(desc,GPIO_VALUE_HIGH);nanosleep(&n_sleep, NULL); // 0.5s 高电平gpio_set_value(desc,GPIO_VALUE_LOW);nanosleep(&n_sleep, NULL); // 0.5s 低电平}gpio_close(desc);return ;
}
#include "watch-dog.h"int func_start()
{int ret = 0;ret=bmc_wd_set(MASK_DISABLE); //mask和disable都是否定if(ret == 0){syslog(LOG_INFO ,"func_start OK\n");}else{syslog(LOG_ERR ,"func_start Fail\n");return -1;}return 0;
}int func_stop()
{int ret = 0;ret=bmc_wd_set(MASK_ENABLE);if(ret == 0){syslog(LOG_INFO ,"func_stop OK\n");}else{syslog(LOG_ERR ,"func_stop Fail\n");return -1;}return 0;
}void usage(void)
{fprintf(stderr, "usage: watch-dog \n");exit (1);
}int func_kick()
{int rc,ret,pid_file;int pid_value;char piddata[12];char file_path[60];pthread_t tid_feed;ret = snprintf(file_path, sizeof(file_path), "/var/run/watch_dog.pid"); // /var/run/a 也可以,记录当前进程pid号if ((ret < 0) || (ret >= sizeof(file_path))) {syslog(LOG_ERR ,"watch_dog:too long for lockfile\n");return -1;}pid_file = open(file_path, O_CREAT | O_RDWR, 0666);if (pid_file < 0) {syslog(LOG_ERR ,"watch_dog: failed to acquire lock\n");exit(1);}else{pid_value=getpid();snprintf(piddata, sizeof(piddata), "%d\n", pid_value);ret=write(pid_file, piddata, sizeof(piddata)); //先open再writeif(ret < 0) {syslog(LOG_ERR ,"watch_dog: write pid err\n");}}rc = flock(pid_file, LOCK_EX | LOCK_NB); // Linux文件锁flock: 检测进程是否已经存在if(rc){if(EWOULDBLOCK == errno){syslog(LOG_ERR ,"Another watch_dog instance is running...\n");exit(1);}}syslog(LOG_INFO ,"watch_dog: daemon started\n");pthread_create(&tid_feed,NULL,(void *)feed_dog_func,NULL); //一个pthread_create只创建一个线程pthread_join(tid_feed,NULL);if (pid_file >= 0) {unlink(file_path); //#include , unlink删除文件}syslog(LOG_INFO ,"watch_dog: daemon end\n");return 0;
}wd_func wd_func_judge(char * desc)
{if (!strcmp(desc, "start")){ // strcmp相同返回0,if(1)执行,shell中if(0)执行return WD_FUNC_START;}else if (!strcmp(desc, "stop")){return WD_FUNC_STOP;}else if (!strcmp(desc, "kick")){return WD_FUNC_KICK;}return WD_FUNC_UNKNOWN;
}int main(int argc, char* argv[])
{wd_func wd_func_sel = WD_FUNC_UNKNOWN;if (argc != 2) {usage();}wd_func_sel = wd_func_judge(argv[1]);if ( wd_func_sel == WD_FUNC_UNKNOWN ){usage();}switch (wd_func_sel){case WD_FUNC_START :func_start();break;case WD_FUNC_STOP :func_stop();break;case WD_FUNC_KICK :func_kick();break;default :break;}return 0;
}
#
all: watch-dog
SRC = $(wildcard ./*.c)
CFLAGS += -Wall -Werror -D _XOPEN_SOURCE -pthread -lm -std=c99watch-dog: $(SRC)$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS).PHONY: cleanclean:rm -rf *.o watch-dog
exec /usr/local/bin/watch-dog kick
WDTFUNC=/usr/local/bin/watch-dog
# /etc/init.d/setup-watch-dog.sh: start and stop the watch-dog
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin:/usr/local/bin"
case "$1" instart)echo -n "Starting watch dog kick daemon..."runsv /etc/sv/watch-dog > /dev/null 2>&1 & # runsv找/etc/sv/watch-dog/run文件运行echo "done.";;stop)echo -n "Stopping watch dog daemon..."$WDTFUNC stop > /dev/null 2>&1 &echo "done.";;*)echo "Usage: /etc/init.d/setup-watch-dog.sh {start|stop}"exit 1;;
esac
exit 0
SUMMARY = "watch dog Daemon"
DESCRIPTION = "Daemon for watch dog"
SECTION = "base"
PR = "r1"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a"
SRC_URI = "file://COPYING \file://main.c \file://watch-dog.c \file://watch-dog.h \file://Makefile \file://setup-watch-dog.sh \file://run-watch-dog.sh \"
S = "${WORKDIR}"
binfiles = "watch-dog \"
pkgdir = "watch-dog"
LDFLAGS = "-lgpio-ctrl"
DEPENDS += "libgpio-ctrl update-rc.d-native"
RDEPENDS_${PN} += "libgpio-ctrl bash"install_sysv() {install -d ${D}${sysconfdir}/init.dinstall -d ${D}${sysconfdir}/rcS.dinstall -d ${D}${sysconfdir}/svinstall -d ${D}${sysconfdir}/sv/watch-doginstall -d ${D}${sysconfdir}/watch-doginstall -m 755 setup-watch-dog.sh ${D}${sysconfdir}/init.d/setup-watch-dog.shinstall -m 755 run-watch-dog.sh ${D}${sysconfdir}/sv/watch-dog/run #将run-watch-dog.sh复制到/etc/sv/watch-dog/run文件里update-rc.d -r ${D} setup-watch-dog.sh defaults 93 5 #defaults :开机自动执行setup-watch-dog.sh start ,reboot自动执行setup-watch-dog.sh stop
}do_install() {dst="${D}/usr/local/fbpackages/${pkgdir}"bin="${D}/usr/local/bin"install -d $dstinstall -d $binfor f in ${binfiles}; doinstall -m 755 $f ${dst}/$fln -snf ../fbpackages/${pkgdir}/$f ${bin}/$fdoneinstall_sysv
}FBPACKAGEDIR = "${prefix}/local/fbpackages"
FILES_${PN} = "${FBPACKAGEDIR}/watch-dog ${prefix}/local/bin ${sysconfdir}"

// obmc-pal.c
/* IPMI SEL: System Firmware Error string table */
struct system_fw_progress {uint8_t EventData1;char DecodeString[128];
};struct system_fw_progress system_fw_error[] = {{0x00, "Unspecified"}, // 一个{}就是一个system_fw_progress结构体,129字节{0x01, "No system memory is physically installed in the system"},{0x02, "No usable system memory, all installed memory has experienced an unrecoverable failure"}, // 88字节{0x03, "Unrecoverable hard-disk/ATAPI/IDE device failure"},{0x04, "Unrecoverable system-board failure"},{0x05, "Unrecoverable diskette subsystem failure"},{0x06, "Unrecoverable hard-disk controller failure"},{0x07, "Unrecoverable PS/2 or USB keyboard failure"},{0x08, "Removable boot media not found"},{0x09, "Unrecoverable video controller failure"},{0x0A, "No video device detected"},{0x0B, "Firmware (BIOS) ROM corruption detected"},{0x0C, "CPU voltage mismatch"},{0x0D, "CPU speed matching failure"},
};struct system_fw_progress system_fw_hang_or_progress[] = {{0x00, "Unspecified"},{0x01, "Memory initialization"},{0x02, "Hard-disk initialization"},{0x03, "Secondary processor(s) initialization"},{0x04, "User authentication"},{0x05, "User-initiated system setup"},{0x06, "USB resource configuration"},{0x07, "PCI resource configuration"},{0x08, "Option ROM initialization"},{0x09, "Video initialization"},{0x0A, "Cache initialization"},{0x0B, "SM Bus initialization"},{0x0C, "Keyboard controller initialization"},{0x0D, "Embedded controller/management controller initialization"},{0x0E, "Docking station attachment"},{0x0F, "Enabling docking station"},{0x10, "Docking station ejection"},{0x11, "Disabling docking station"},{0x12, "Calling operating system wake-up vector"},{0x13, "Starting operating system boot process, e.g. calling Int 19h"},{0x14, "Baseboard or motherboard initialization"},{0x15, "reserved"},{0x16, "Floppy initialization"},{0x17, "Keyboard test"},{0x18, "Pointing device test"},{0x19, "Primary processor initialization"},
};uint8_t *ed = &event_data[3];char temp_log[512] = {0};char add_sol_log_com[512] = "logger -p local3.info ";case POST_ERROR:if (((ed[0] >> 6) & 0x03) == 0x3) { // table29 eventdata1第6和7位为11switch (ed[0] & 0xF) { // table29取eventdata1低四位case 0x00: // sensor offsetstrcat(error_log, "System Firmware Error (POST Error), IPMI Post Code"); // 50字节if (ed[1] < (sizeof(system_fw_error) / sizeof(system_fw_error[0]))) { // 13*129/129=0x0dsprintf(temp_log, ", %s", system_fw_error[ed[1]].DecodeString); // 88字节,ed[1]即eventdata2} else {sprintf(temp_log, ", reserved");}break;case 0x01:strcat(error_log, "System Firmware Hang, IPMI Post Code");case 0x02:if (strcmp(error_log, "") == 0) {strcat(error_log, "System Firmware Progress, IPMI Post Code");}if (ed[1] < (sizeof(system_fw_hang_or_progress) / sizeof(system_fw_hang_or_progress[0]))) {sprintf(temp_log, ", %s", system_fw_hang_or_progress[ed[1]].DecodeString);} else {sprintf(temp_log, ", reserved");}break;default:sprintf(temp_log, "Unknown");break;}strcat(error_log, temp_log); //138// send post code sel to sol logsprintf(temp_log, " '%s' ", error_log);strcat(add_sol_log_com, temp_log);system(add_sol_log_com);break;

