Jelajahi Sumber

Erste Testversion mit Image-Upload.

Rind 5 tahun lalu
induk
melakukan
f52af29e05
15 mengubah file dengan 1031 tambahan dan 404 penghapusan
  1. 1 1
      Makefile
  2. 33 16
      defines.h
  3. 406 227
      drvmain.c
  4. 29 0
      gfaspi.h
  5. 101 84
      kfirmware.c
  6. 1 0
      kfirmware.h
  7. 89 9
      kspi.c
  8. 5 0
      kspi.h
  9. 44 0
      ksync.c
  10. 23 0
      ksync.h
  11. 91 19
      ktiva.c
  12. 4 1
      ktiva.h
  13. 189 41
      sfsattrib.c
  14. 13 4
      sfsattrib.h
  15. 2 2
      test/main.c

+ 1 - 1
Makefile

@@ -2,7 +2,7 @@
 TARGET_MODULE:=gfaspi
 PWD := $(shell pwd)
 
-$(TARGET_MODULE)-objs := drvmain.o kfile.o sfsattrib.o kspi.o ktiva.o kfirmware.o
+$(TARGET_MODULE)-objs := drvmain.o kfile.o sfsattrib.o kspi.o ktiva.o kfirmware.o ksync.o
 obj-m := $(TARGET_MODULE).o
 
 

+ 33 - 16
defines.h

@@ -4,6 +4,8 @@
 #if !defined(AGD_DEFINES_H__C7EAD575_99C7_4047_8E24_F5887CACEC73__INCLUDED_)
 #define AGD_DEFINES_H__C7EAD575_99C7_4047_8E24_F5887CACEC73__INCLUDED_
 
+#include "gfaspi.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif	//	__cplusplus
@@ -11,9 +13,9 @@ extern "C" {
 /////////////////////////////////////////////////////////////////////////////
 // defines.h - Declarations:
 
-
-#define _EXTENDED_ERROR_CHECK			1
-#define _SUPPORT_LEGACY_UPTIME			0
+#define _SITARA_EGGELSBERG										0
+#define _EXTENDED_ERROR_CHECK									1
+#define _SUPPORT_LEGACY_UPTIME									0
 
 /////////////////////////////////////////////////////////////////////////////
 
@@ -24,19 +26,15 @@ extern "C" {
 #define KFW_IMG_HEADER_PREFIX_0									((unsigned int)0xFF01FF02)
 #define KFW_IMG_HEADER_PREFIX_1									((unsigned int)0xFF03FF04)
 
+/////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
 
-
-typedef struct _TIVA_ADC
+typedef struct _TIVA_MAT_SER
 {
-	int UVers;
-	int UBatV3;
-	int Temp;
-	int UV5Vsys;
-	int UV3V6Bat;
-	int TempTIVA;
-}TIVA_ADC, *LPTIVA_ADC;
-typedef const TIVA_ADC *LPCTIVA_ADC;
+	char szImgMaterialNum[KFW_MAX_IMG_MATERIAL_NUM_LENGTH];
+	char szImgNameBuild[KFW_MAX_IMG_NAME_BUILD_LENGTH];
+}TIVA_MAT_SER, *LPTIVA_MAT_SER;
+typedef const TIVA_MAT_SER *LPCTIVA_MAT_SER;
 
 /////////////////////////////////////////////////////////////////////////////
 
@@ -72,6 +70,7 @@ typedef struct _TIVA_UPLOAD_INFO
 	LPCKFW_IMG_HEADER  pkih;
 	const char *pszMat;
 	const char *pszBld;
+	atomic_t flgUIReady;
 }TIVA_UPLOAD_INFO, *LPTIVA_UPLOAD_INFO;
 typedef const TIVA_UPLOAD_INFO *LPCTIVA_UPLOAD_INFO;
 
@@ -79,6 +78,7 @@ typedef const TIVA_UPLOAD_INFO *LPCTIVA_UPLOAD_INFO;
 /////////////////////////////////////////////////////////////////////////////
 
 
+#define _min(a, b)						(((a) < (b)) ? (a) : (b))
 #define _countof(a)						(sizeof(a) / sizeof(*a))
 #define _JIFFY_DIFF(a, b)				((long)((unsigned long)(a) - (unsigned long)(b)))
 #define KALERT(...)						printk(KERN_ALERT __VA_ARGS__)
@@ -87,16 +87,33 @@ typedef const TIVA_UPLOAD_INFO *LPCTIVA_UPLOAD_INFO;
 /////////////////////////////////////////////////////////////////////////////
 
 
+#if _SITARA_EGGELSBERG
+#define _SPI_SPEED_HZ					100000
+#else	//	_SITARA_EGGELSBERG
 #define _SPI_SPEED_HZ					1000000
+#endif	//	_SITARA_EGGELSBERG
 #define _SPI_BITS_PER_WORD				8
 #define _SPI_DEVICE						"/dev/spidev1.0"
 #define _TIMER_INTERVAL					(jiffies + HZ) // 1 sec
 #define _FIRMWARE_PAGES_COUNT			6
 #define _FIRMWARE_BUFFER_SIZE			(64 * PAGE_SIZE) // = 2 ^ 6 * PAGE_SIZE
 
-#define KFW_DEFAULT_BASE_ADDRESS		0 // 0x2000
-#define KFW_DEFAULT_UPLOAD_BLOCKSIZE	8
-#define KFW_MIN_HAS_MATERIAL_NR_VERSION	0x0201
+#define _BACKLIGHT_FREQ_MIN_HZ			10
+#define _BACKLIGHT_FREQ_MAX_HZ			10000
+#define _BACKLIGHT_DEF_FREQ_HZ			1000
+#define _BACKLIGHT_DEF_BRIGHT_PERC		50
+
+#define KFW_DEFAULT_PAGE_ERASE_TIME		20
+#define KFW_FLASH_PAGE_SIZE				1024
+
+#define KFW_DEFAULT_BASE_ADDRESS		0
+//#define KFW_DEFAULT_BASE_ADDRESS		0x2000
+
+#define KFW_MIN_UPLOAD_BLOCKSIZE		4
+#define KFW_MAX_UPLOAD_BLOCKSIZE		76
+#define KFW_DEFAULT_UPLOAD_BLOCKSIZE	76
+
+#define KFW_MIN_HAS_MATERIAL_NR_VERSION	0x0202
 
 
 /////////////////////////////////////////////////////////////////////////////

+ 406 - 227
drvmain.c

@@ -16,60 +16,96 @@
 #include "ktiva.h"
 #include "sfsattrib.h"
 #include "kfirmware.h"
+#include "ksync.h"
 
 /////////////////////////////////////////////////////////////////////////////
 
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("GfA");
 
-#define _THREAD_DELAY_JIFFIES				5
+#define _SLEEP_DELAY_JIFFIES				5
 #define _IS_REVIVE_STATE(ret)				((ret) != -ECOMM)
 
 /////////////////////////////////////////////////////////////////////////////
 // sys fs
 
-static struct kobject *g_pKoGfa = NULL, *g_pKoTiva = NULL;
+static struct kobject *g_pKoGfa = NULL, *g_pKoTiva = NULL, *g_pKoBacklight = NULL, *g_pKoADC = NULL, *g_pKoFirmware = NULL;
 static bool g_bHasFwVersion = false;
+static atomic_t g_flgSysFsRunning;
 
 /////////////////////////////////////////////////////////////////////////////
 // worker threads
 
 static void _SysFsWorkProc(struct work_struct *work);
 static void _FwUploadWorkProc(struct work_struct *work);
+static void _BacklightWorkProc(struct work_struct *work);
 
 static struct workqueue_struct *g_pwq = NULL;
 static DECLARE_WORK(g_sysFsWorkObj, _SysFsWorkProc);
 static DECLARE_WORK(g_fwUploadWorkObj, _FwUploadWorkProc);
+static DECLARE_WORK(g_backLightWorkObj, _BacklightWorkProc);
 
 /////////////////////////////////////////////////////////////////////////////
 // timer
 
-static volatile bool g_bTimerRunning = false;
-static struct timer_list g_jiq_timer;
+static atomic_t g_flgTimerRunning;
+static struct timer_list g_timer_list;
 
 /////////////////////////////////////////////////////////////////////////////
 
 typedef enum _WorkerState
 {
 	WS_SysFs,
-	WS_FwUpload
+	WS_FwUpload,
+	WS_Backlight,
+	WS_Idle
 }WorkerState;
 
-static TIVA_UPLOAD_INFO g_tui;
+/////////////////////////////////////////////////////////////////////////////
+
+static bool _GetSysFsRunning(void)
+{
+	return !!atomic_read(&g_flgSysFsRunning);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static void _SetSysFsRunning(bool bRunning)
+{
+	atomic_set(&g_flgSysFsRunning, bRunning ? 1 : 0);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static bool _GetTimerRunning(void)
+{
+	return !!atomic_read(&g_flgTimerRunning);
+}
 
 /////////////////////////////////////////////////////////////////////////////
 
-static void OnJigTimer(unsigned long ptr)
+static void _SetTimerRunning(bool bRunning)
+{
+	atomic_set(&g_flgTimerRunning, bRunning ? 1 : 0);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static void _WorkScheduler(unsigned long ptr)
 {
 	static unsigned int nPass = 0;
 	static WorkerState ws = WS_SysFs;
 
-//	KALERT("%s: %d, %p\n", __FUNCTION__, g_bTimerRunning ? 1 : 0, g_pwq);
+//	KALERT("%s: %d, %p\n", __FUNCTION__, _GetTimerRunning() ? 1 : 0, g_pwq);
 
-	if(g_bTimerRunning && g_pwq)
+	if(_GetTimerRunning())
 	{
-		if(KfwQueryUploadInfo(&g_tui))
+		if(KfwUploadInfoReady())
 			ws = WS_FwUpload;
+		else if(SfAttBacklightChanged())
+			ws = WS_Backlight;
+		else if(!_GetSysFsRunning())
+			ws = WS_Idle;
 
 		switch(ws)
 		{
@@ -85,9 +121,7 @@ static void OnJigTimer(unsigned long ptr)
 			}
 			else
 			{
-				mutex_lock(&g_mutex);
-				mod_timer(&g_jiq_timer, _TIMER_INTERVAL);
-				mutex_unlock(&g_mutex);
+				mod_timer(&g_timer_list, _TIMER_INTERVAL);
 			}
 			break;
 		case WS_FwUpload:
@@ -96,8 +130,18 @@ static void OnJigTimer(unsigned long ptr)
 				KALERT("%s: queue_work failed\n", __FUNCTION__);
 			}
 			ws = WS_SysFs;
-//			nPass = 2;
-			nPass = 1;
+			nPass = 2;
+			break;
+		case WS_Backlight:
+			if(!queue_work(g_pwq, &g_backLightWorkObj))
+			{
+				KALERT("%s: queue_work failed\n", __FUNCTION__);
+			}
+			ws = WS_SysFs;
+			nPass = 2;
+			break;
+		case WS_Idle:
+			mod_timer(&g_timer_list, _TIMER_INTERVAL);
 			break;
 		}
 	}
@@ -109,74 +153,77 @@ static void OnJigTimer(unsigned long ptr)
 // https://stackoverflow.com/questions/16367623/using-the-linux-sysfs-notify-call
 //
 
-static void _FwUploadWorkProc(struct work_struct *work)
+static void _BacklightWorkProc(struct work_struct *work)
 {
 	struct file *pfSpiDev = NULL;
-	uint8_t mode	= 0;
-	uint8_t bits	= 0;
-	uint32_t speed	= 0;
+	int ret;
 
 	if((pfSpiDev = kf_open(_SPI_DEVICE, O_RDWR, 0)))
 	{
 		do
 		{
-			unsigned char stat = 0xFF;
-
-			if(kspi_write_mode(pfSpiDev, SPI_MODE_3) < 0)
-			{
-				KALERT("%s: kspi_write_mode failed!\n", __FUNCTION__);
-				break;
-			}
+			unsigned int nFrequency = SfAttGetBacklightFrequency();
+			unsigned int nBrightness = SfAttGetBacklightBrightness();
 
-			if(kspi_read_mode(pfSpiDev, &mode) < 0)
-			{
-				KALERT("%s: kspi_read_mode failed!\n", __FUNCTION__);
-				break;
-			}
+			/////////////////////////////////////////////////////////////////
 
-			if(mode != SPI_MODE_3)
+			if(!KSpiInit(pfSpiDev))
 			{
-				KALERT("%s: Invalid mode!\n", __FUNCTION__);
 				break;
 			}
 
 			/////////////////////////////////////////////////////////////////
 
-			if(kspi_write_bits_per_word(pfSpiDev, _SPI_BITS_PER_WORD) < 0)
+			KALERT("%s: Set backlight frequency to %u Hz, brightness to %u %%\n", __FUNCTION__, nFrequency, nBrightness);
+			if((ret = TivaCmdSetBacklight(pfSpiDev, nFrequency, nBrightness)) != 0)
 			{
-				KALERT("%s: kspi_write_bits_per_word failed!\n", __FUNCTION__);
+				KALERT("%s: TivaCmdSetBacklight failed: %d!\n", __FUNCTION__, ret);
 				break;
 			}
+		}
+		while(0);
 
-			if(kspi_read_bits_per_word(pfSpiDev, &bits) < 0)
-			{
-				KALERT("%s: kspi_read_bits_per_word failed!\n", __FUNCTION__);
-				break;
-			}
+		kf_close(pfSpiDev);
+	}
+	else
+	{
+		KALERT("%s: kf_open failed\n", __FUNCTION__);
+	}
 
-			if(bits != _SPI_BITS_PER_WORD)
-			{
-				KALERT("%s: Invalid bits per word!\n", __FUNCTION__);
-				break;
-			}
+	if(_GetTimerRunning())
+	{
+		ksync_lock();
+		mod_timer(&g_timer_list, _TIMER_INTERVAL);
+		ksync_unlock();
+	}
+}
 
-			/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
 
-			if(kspi_write_max_speed_hz(pfSpiDev, _SPI_SPEED_HZ) < 0)
-			{
-				KALERT("%s: kspi_write_max_speed_hz failed!\n", __FUNCTION__);
-				break;
-			}
+static void _FwUploadWorkProc(struct work_struct *work)
+{
+	int nRet, i;
+	bool bSuccess = false, bReset = true;
+    unsigned long start = jiffies;
+	struct file *pfSpiDev = NULL;
+	TIVA_UPLOAD_INFO tui;
 
-			if(kspi_read_max_speed_hz(pfSpiDev, &speed) < 0)
-			{
-				KALERT("%s: kspi_read_max_speed_hz failed!\n", __FUNCTION__);
-				break;
-			}
+	if(!KfwQueryUploadInfo(&tui))
+	{
+		KALERT("%s: Upload info not ready!!\n", __FUNCTION__);
+		return;
+	}
+
+	if((pfSpiDev = kf_open(_SPI_DEVICE, O_RDWR, 0)))
+	{
+		do
+		{
+			unsigned char stat = 0xFF;
+			size_t nCntBlocks, nCbToSend, nCbBlock, nCntFlashPages;
+			const unsigned char *pbToSend;
 
-			if(speed != _SPI_SPEED_HZ)
+			if(!KSpiInit(pfSpiDev))
 			{
-				KALERT("%s: Invalid max. speed!\n", __FUNCTION__);
 				break;
 			}
 
@@ -186,87 +233,170 @@ static void _FwUploadWorkProc(struct work_struct *work)
 			{
 			}
 
-			if(TivaCmdStartBootloader(pfSpiDev) < 0)
+			if((nRet = TivaCmdStartBootloader(pfSpiDev)) < 0)
 			{
 				KALERT("%s: TivaCmdStartBootloader failed!\n", __FUNCTION__);
 				break;
 			}
 
+			ksync_lock();
 			g_hw = -1;
 			g_sw = -1;
 			g_bHasFwVersion = false;
-			sysfs_notify(g_pKoTiva, NULL, "version");
+			ksync_unlock();
+			sysfs_notify(g_pKoFirmware, NULL, "version");
 
 			KALERT("%s: Started bootloader!\n", __FUNCTION__);
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(_THREAD_DELAY_JIFFIES);
+			ksync_sleep_jiffies(_SLEEP_DELAY_JIFFIES);
 
-			if(TivaCmdGetBootloaderStatus(pfSpiDev, &stat) < 0)
+			if((nRet = TivaCmdGetBootloaderStatus(pfSpiDev, &stat)) < 0)
 			{
-				KALERT("%s: TivaCmdGetStatus failed!\n", __FUNCTION__);
+				KALERT("%s: TivaCmdGetBootloaderStatus failed!\n", __FUNCTION__);
 				break;
 			}
 
-			KALERT("%s: Status: 0x%02hhX\n", __FUNCTION__, stat);
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(_THREAD_DELAY_JIFFIES);
+			KALERT("%s: Bootloader Status: 0x%02hhX\n", __FUNCTION__, stat);
+			ksync_sleep_jiffies(_SLEEP_DELAY_JIFFIES);
 
-			if(TivaCmdPing(pfSpiDev) < 0)
+			if((nRet = TivaCmdPing(pfSpiDev)) < 0)
 			{
 				KALERT("%s: TivaCmdPing failed!\n", __FUNCTION__);
 				break;
 			}
 
-			KALERT("%s: Ping success!\n", __FUNCTION__);
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(_THREAD_DELAY_JIFFIES);
+			KALERT("%s: Bootloader Ping success!\n", __FUNCTION__);
+			ksync_sleep_jiffies(_SLEEP_DELAY_JIFFIES);
 
-			if(TivaCmdGetBootloaderStatus(pfSpiDev, &stat) < 0)
+			if((nRet = TivaCmdGetBootloaderStatus(pfSpiDev, &stat)) < 0)
 			{
-				KALERT("%s: TivaCmdGetStatus failed!\n", __FUNCTION__);
+				KALERT("%s: TivaCmdGetBootloaderStatus failed!\n", __FUNCTION__);
 				break;
 			}
 
-			KALERT("%s: Status: 0x%02hhX\n", __FUNCTION__, stat);
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(_THREAD_DELAY_JIFFIES);
+			KALERT("%s: Bootloader Status: 0x%02hhX\n", __FUNCTION__, stat);
+			ksync_sleep_jiffies(_SLEEP_DELAY_JIFFIES);
+
+			/////////////////////////////////////////////////////////////////
+
+			nCbToSend = (tui.nCbData + (KFW_MIN_UPLOAD_BLOCKSIZE - 1) / KFW_MIN_UPLOAD_BLOCKSIZE * KFW_MIN_UPLOAD_BLOCKSIZE);
+			pbToSend = (const unsigned char*)tui.pData;
+			nCntBlocks = (nCbToSend + KFW_DEFAULT_UPLOAD_BLOCKSIZE - 1) / KFW_DEFAULT_UPLOAD_BLOCKSIZE;
+			nCntFlashPages = (nCntBlocks * KFW_DEFAULT_UPLOAD_BLOCKSIZE + KFW_FLASH_PAGE_SIZE - 1) / KFW_FLASH_PAGE_SIZE;
+			KALERT("%s: Start Download of %zu Bytes (%zu Blocks) at Address 0x%08X\n", __FUNCTION__, nCbToSend, nCntBlocks, KFW_DEFAULT_BASE_ADDRESS);
 
-			if(TivaCmdReset(pfSpiDev) < 0)
+			if((nRet = TivaCmdStartDownload(pfSpiDev, KFW_DEFAULT_BASE_ADDRESS, nCbToSend)) != 0)
 			{
-				KALERT("%s: TivaCmdReset failed!\n", __FUNCTION__);
+				KALERT("%s: TivaCmdStartDownload failed: %d!\n", __FUNCTION__, nRet);
 				break;
 			}
 
-			KALERT("%s: Started firmware!\n", __FUNCTION__);
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(_THREAD_DELAY_JIFFIES);
+			ksync_sleep_jiffies((long)(nCntFlashPages * KFW_DEFAULT_PAGE_ERASE_TIME));
+
+			if((nRet = TivaCmdGetBootloaderStatus(pfSpiDev, &stat)) < 0)
+			{
+				KALERT("%s: TivaCmdGetBootloaderStatus failed!\n", __FUNCTION__);
+				break;
+			}
 
-			if(TivaCmdGetStatus(pfSpiDev, &stat) < 0)
+			if(stat != COMMAND_RET_SUCCESS)
 			{
-				KALERT("%s: TivaCmdGetStatus failed!\n", __FUNCTION__);
+				KALERT("%s: TivaCmdGetBootloaderStatus returned 0x%02hhX!\n", __FUNCTION__, stat);
 				break;
 			}
 
-			KALERT("%s: Status: 0x%02hhX\n", __FUNCTION__, stat);
+			KALERT("%s: Bootloader Status: 0x%02hhX\n", __FUNCTION__, stat);
+			KALERT("%s: Sending data ...\n", __FUNCTION__);
+			ksync_sleep_jiffies(_SLEEP_DELAY_JIFFIES);
+
+			for(i = 0; i < nCntBlocks; ++i)
+			{
+				nCbBlock = _min(KFW_DEFAULT_UPLOAD_BLOCKSIZE, nCbToSend);
+				if((nRet = TivaCmdSendDataBlock(pfSpiDev, pbToSend, nCbBlock)) != 0)
+				{
+					bReset = false;
+					KALERT("%s: TivaCmdSendDataBlock failed!\n", __FUNCTION__);
+					break;
+				}
+				pbToSend += nCbBlock;
+				nCbToSend -= nCbBlock;
+
+				if(i && !(i % 64))
+				{
+					KALERT("%s: %zu Blocks sent.\n", __FUNCTION__, i);
+				}
+
+//				ksync_sleep_jiffies(1);
+
+				if((nRet = TivaCmdGetBootloaderStatus(pfSpiDev, &stat)) < 0)
+				{
+					bReset = false;
+					KALERT("%s: TivaCmdGetBootloaderStatus failed!\n", __FUNCTION__);
+					break;
+				}
+
+				if(stat != COMMAND_RET_SUCCESS)
+				{
+					bReset = false;
+					KALERT("%s: TivaCmdGetBootloaderStatus returned 0x%02hhX!\n", __FUNCTION__, stat);
+					break;
+				}
+
+//				ksync_sleep_jiffies(1);
+			}
+
+			KALERT("%s: %zu Blocks sent.\n", __FUNCTION__, i);
+			ksync_sleep_jiffies(_SLEEP_DELAY_JIFFIES);
+
+			/////////////////////////////////////////////////////////////////
+
+			if(bReset)
+			{
+				if((nRet = TivaCmdReset(pfSpiDev)) < 0)
+				{
+					KALERT("%s: TivaCmdReset failed!\n", __FUNCTION__);
+					break;
+				}
+
+				KALERT("%s: Started firmware!\n", __FUNCTION__);
+				ksync_sleep_jiffies(_SLEEP_DELAY_JIFFIES);
+
+				if((nRet = TivaCmdGetStatus(pfSpiDev, &stat)) < 0)
+				{
+					KALERT("%s: TivaCmdGetStatus failed!\n", __FUNCTION__);
+					break;
+				}
+
+				KALERT("%s: FW Status: 0x%02hhX\n", __FUNCTION__, stat);
 
-//			KALERT("%s: data: 0x%p, cb: %zu, mat: %s, bld: %s\n", __FUNCTION__, g_tui.pData, g_tui.nCbData, g_tui.pszMat, g_tui.pszBld);
+				bSuccess = true;
+			}
+//			KALERT("%s: data: 0x%p, cb: %zu, mat: %s, bld: %s\n", __FUNCTION__, tui.pData, tui.nCbData, tui.pszMat, tui.pszBld);
 		}
 		while(0);
 
-		SfAttLockFirmware(false);
 		kf_close(pfSpiDev);
+		SfAttLockFirmware(false);
 	}
 	else
 	{
 		KALERT("%s: kf_open failed\n", __FUNCTION__);
 	}
 
-	if(g_bTimerRunning)
+	if(!bSuccess)
+	{
+		KALERT("%s: Firmware-Upload failed! Stopping all activities!\n", __FUNCTION__);
+	}
+
+	_SetSysFsRunning(bSuccess);
+
+	if(_GetTimerRunning())
 	{
-		mutex_lock(&g_mutex);
-		mod_timer(&g_jiq_timer, _TIMER_INTERVAL);
-		mutex_unlock(&g_mutex);
+		ksync_lock();
+		mod_timer(&g_timer_list, _TIMER_INTERVAL);
+		ksync_unlock();
 	}
+
+	KALERT("%s: jiffies: %lu\n", __FUNCTION__, _JIFFY_DIFF(jiffies, start));
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -278,77 +408,19 @@ static void _SysFsWorkProc(struct work_struct *work)
 	int hw, sw, ret;
 	unsigned long long nUpTime;
 	struct file *pfSpiDev = NULL;
-	uint8_t mode	= 0;
-	uint8_t bits	= 0;
-	uint32_t speed	= 0;
-//	unsigned long start = jiffies;
-
-//	KALERT("%s, Ctx: \"%s\"-(%d)\n", __FUNCTION__, current->comm, current->pid);
 
 	if((pfSpiDev = kf_open(_SPI_DEVICE, O_RDWR, 0)))
 	{
 		do
 		{
-			if(kspi_write_mode(pfSpiDev, SPI_MODE_3) < 0)
-			{
-				KALERT("%s: kspi_write_mode failed!\n", __FUNCTION__);
-				break;
-			}
-
-			if(kspi_read_mode(pfSpiDev, &mode) < 0)
-			{
-				KALERT("%s: kspi_read_mode failed!\n", __FUNCTION__);
-				break;
-			}
-
-			if(mode != SPI_MODE_3)
-			{
-				KALERT("%s: Invalid mode!\n", __FUNCTION__);
-				break;
-			}
-
-			/////////////////////////////////////////////////////////////////
-
-			if(kspi_write_bits_per_word(pfSpiDev, _SPI_BITS_PER_WORD) < 0)
-			{
-				KALERT("%s: kspi_write_bits_per_word failed!\n", __FUNCTION__);
-				break;
-			}
-
-			if(kspi_read_bits_per_word(pfSpiDev, &bits) < 0)
-			{
-				KALERT("%s: kspi_read_bits_per_word failed!\n", __FUNCTION__);
-				break;
-			}
-
-			if(bits != _SPI_BITS_PER_WORD)
-			{
-				KALERT("%s: Invalid bits per word!\n", __FUNCTION__);
-				break;
-			}
-
-			/////////////////////////////////////////////////////////////////
-
-			if(kspi_write_max_speed_hz(pfSpiDev, _SPI_SPEED_HZ) < 0)
-			{
-				KALERT("%s: kspi_write_max_speed_hz failed!\n", __FUNCTION__);
-				break;
-			}
-
-			if(kspi_read_max_speed_hz(pfSpiDev, &speed) < 0)
-			{
-				KALERT("%s: kspi_read_max_speed_hz failed!\n", __FUNCTION__);
-				break;
-			}
-
-			if(speed != _SPI_SPEED_HZ)
+			if(!KSpiInit(pfSpiDev))
 			{
-				KALERT("%s: Invalid max. speed!\n", __FUNCTION__);
 				break;
 			}
 
 			/////////////////////////////////////////////////////////////////
 
+#if !_SITARA_EGGELSBERG
 			if(	(ret = TivaCmdPing(pfSpiDev)) < 0 &&
 				_IS_REVIVE_STATE(ret))
 			{
@@ -356,10 +428,10 @@ static void _SysFsWorkProc(struct work_struct *work)
 				TivaRevive(pfSpiDev);
 			}
 
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(_THREAD_DELAY_JIFFIES);
+			ksync_sleep_jiffies(_SLEEP_DELAY_JIFFIES);
 
 			/////////////////////////////////////////////////////////////////
+			// firmware
 
 			if(!g_bHasFwVersion)
 			{
@@ -367,25 +439,31 @@ static void _SysFsWorkProc(struct work_struct *work)
 				{
 					if((g_hw != hw) || (g_sw != sw))
 					{
+						ksync_lock();
 						g_hw = hw;
 						g_sw = sw;
-						sysfs_notify(g_pKoTiva, NULL, "version");
+						ksync_unlock();
+						sysfs_notify(g_pKoFirmware, NULL, "version");
+						KALERT("%s: TivaCmdGetFirmwareVersion: HW %d, SW: %d\n", __FUNCTION__, g_hw, g_sw);
 					}
 
 					g_bHasFwVersion = true;
 				}
-				else if(_IS_REVIVE_STATE(ret))
+				else
 				{
-					KALERT("%s: TivaCmdGetFirmwareVersion failed: %d - call TivaRevive\n", __FUNCTION__, ret);
-					TivaRevive(pfSpiDev);
+					if(_IS_REVIVE_STATE(ret))
+					{
+						KALERT("%s: TivaCmdGetFirmwareVersion failed: %d - call TivaRevive\n", __FUNCTION__, ret);
+						TivaRevive(pfSpiDev);
+					}
 					break;
 				}
 
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(_THREAD_DELAY_JIFFIES);
+				ksync_sleep_jiffies(_SLEEP_DELAY_JIFFIES);
 			}
 
 			/////////////////////////////////////////////////////////////////
+			// ADC
 
 			if((ret = TivaCmdGetADC(pfSpiDev, &tadc)) == 0)
 			{
@@ -393,49 +471,61 @@ static void _SysFsWorkProc(struct work_struct *work)
 
 				if(g_tadc.UVers != tadc.UVers)
 				{
+					ksync_lock();
 					g_tadc.UVers = tadc.UVers;
+					ksync_unlock();
 					bModified = true;
-					sysfs_notify(g_pKoTiva, NULL, "UVers");
+					sysfs_notify(g_pKoADC, NULL, "UVers");
 				}
 
 				if(g_tadc.UBatV3 != tadc.UBatV3)
 				{
+					ksync_lock();
 					g_tadc.UBatV3 = tadc.UBatV3;
+					ksync_unlock();
 					bModified = true;
-					sysfs_notify(g_pKoTiva, NULL, "UBatV3");
+					sysfs_notify(g_pKoADC, NULL, "UBatV3");
 				}
 
 				if(g_tadc.Temp != tadc.Temp)
 				{
+					ksync_lock();
 					g_tadc.Temp = tadc.Temp;
+					ksync_unlock();
 					bModified = true;
-					sysfs_notify(g_pKoTiva, NULL, "TempBoard");
+					sysfs_notify(g_pKoADC, NULL, "TempBoard");
 				}
 
 				if(g_tadc.UV5Vsys != tadc.UV5Vsys)
 				{
+					ksync_lock();
 					g_tadc.UV5Vsys = tadc.UV5Vsys;
+					ksync_unlock();
 					bModified = true;
-					sysfs_notify(g_pKoTiva, NULL, "UV5Vsys");
+					sysfs_notify(g_pKoADC, NULL, "UV5Vsys");
 				}
 
 				if(g_tadc.UV3V6Bat != tadc.UV3V6Bat)
 				{
+					ksync_lock();
 					g_tadc.UV3V6Bat = tadc.UV3V6Bat;
+					ksync_unlock();
 					bModified = true;
-					sysfs_notify(g_pKoTiva, NULL, "UV3V6Bat");
+					sysfs_notify(g_pKoADC, NULL, "UV3V6Bat");
 				}
 
 				if(g_tadc.TempTIVA != tadc.TempTIVA)
 				{
+					ksync_lock();
 					g_tadc.TempTIVA = tadc.TempTIVA;
+					ksync_unlock();
 					bModified = true;
-					sysfs_notify(g_pKoTiva, NULL, "TempTIVA");
+					sysfs_notify(g_pKoADC, NULL, "TempTIVA");
 				}
 
 				if(bModified) // if any of the ADC values have changed, signal the binary file
 				{
-					sysfs_notify(g_pKoTiva, NULL, "AdcBin");
+					sysfs_notify(g_pKoADC, NULL, "AdcBin");
 				}
 			}
 			else if(_IS_REVIVE_STATE(ret))
@@ -444,8 +534,7 @@ static void _SysFsWorkProc(struct work_struct *work)
 				TivaRevive(pfSpiDev);
 			}
 
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(_THREAD_DELAY_JIFFIES);
+			ksync_sleep_jiffies(_SLEEP_DELAY_JIFFIES);
 
 			/////////////////////////////////////////////////////////////////
 
@@ -453,8 +542,10 @@ static void _SysFsWorkProc(struct work_struct *work)
 			{
 				if(g_nUpTime != nUpTime)
 				{
+					ksync_lock();
 					g_nUpTime = nUpTime;
-					sysfs_notify(g_pKoTiva, NULL, "Uptime");
+					ksync_unlock();
+					sysfs_notify(g_pKoTiva, NULL, "uptime");
 				}
 			}
 			else if(_IS_REVIVE_STATE(ret))
@@ -463,20 +554,23 @@ static void _SysFsWorkProc(struct work_struct *work)
 				TivaRevive(pfSpiDev);
 			}
 
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(_THREAD_DELAY_JIFFIES);
+			ksync_sleep_jiffies(_SLEEP_DELAY_JIFFIES);
 
 			/////////////////////////////////////////////////////////////////
+#endif	//	_SITARA_EGGELSBERG
 
 			if((ret = TivaCmdGetStatus(pfSpiDev, &stat)) == 0)
 			{
 			}
 			else if(_IS_REVIVE_STATE(ret))
 			{
+#if !_SITARA_EGGELSBERG
 				KALERT("%s: TivaCmdGetStatus failed: %d - call TivaRevive\n", __FUNCTION__, ret);
 				TivaRevive(pfSpiDev);
+#endif	//	_SITARA_EGGELSBERG
 			}
 
+
 			/////////////////////////////////////////////////////////////////
 
 //			KALERT("Worker pass - jiffies: %ld - status: 0x%02hhX\n", _JIFFY_DIFF(jiffies, start), stat);
@@ -490,11 +584,11 @@ static void _SysFsWorkProc(struct work_struct *work)
 		KALERT("%s: kf_open failed\n", __FUNCTION__);
 	}
 
-	if(g_bTimerRunning)
+	if(_GetTimerRunning())
 	{
-		mutex_lock(&g_mutex);
-		mod_timer(&g_jiq_timer, _TIMER_INTERVAL);
-		mutex_unlock(&g_mutex);
+		ksync_lock();
+		mod_timer(&g_timer_list, _TIMER_INTERVAL);
+		ksync_unlock();
 	}
 }
 
@@ -518,70 +612,109 @@ static int drv_init(void)
 			break;
 		}
 
+		if(!(g_pKoBacklight = kobject_create_and_add("backlight", g_pKoTiva)))
+		{
+			KALERT("kobject_create_and_add failed\n");
+			break;
+		}
+
+		if(!(g_pKoADC = kobject_create_and_add("adc", g_pKoTiva)))
+		{
+			KALERT("kobject_create_and_add failed\n");
+			break;
+		}
+
+		if(!(g_pKoFirmware = kobject_create_and_add("firmware", g_pKoTiva)))
+		{
+			KALERT("kobject_create_and_add failed\n");
+			break;
+		}
+
 		/////////////////////////////////////////////////////////////////////
+		// generic
 
-		if(sysfs_create_file(g_pKoTiva, &g_tivaVersionAtt.attr))
+		if(sysfs_create_file(g_pKoTiva, &g_tivaUptimeAtt.attr))
 		{
 			KALERT("sysfs_create_file failed\n");
 			break;
 		}
 
-		if(sysfs_create_file(g_pKoTiva, &g_tivaUptimeAtt.attr))
+		/////////////////////////////////////////////////////////////////////
+		// firmware
+
+		if(sysfs_create_file(g_pKoFirmware, &g_tivaVersionAtt.attr))
 		{
 			KALERT("sysfs_create_file failed\n");
 			break;
 		}
 
-		if(sysfs_create_file(g_pKoTiva, &g_tivaUVersAtt.attr))
+		if(SfAttInit())
+		{
+			if(sysfs_create_bin_file(g_pKoFirmware, &g_tivaFwImageAtt))
+			{
+				KALERT("sysfs_create_file failed\n");
+				break;
+			}
+		}
+
+		/////////////////////////////////////////////////////////////////////
+		// backlight
+
+		if(sysfs_create_file(g_pKoBacklight, &g_tivaBrightnessAtt.attr))
 		{
 			KALERT("sysfs_create_file failed\n");
 			break;
 		}
 
-		if(sysfs_create_file(g_pKoTiva, &g_tivaUBatV3Att.attr))
+		if(sysfs_create_file(g_pKoBacklight, &g_tivaFrequencyAtt.attr))
 		{
 			KALERT("sysfs_create_file failed\n");
 			break;
 		}
 
-		if(sysfs_create_file(g_pKoTiva, &g_tivaTempAtt.attr))
+		/////////////////////////////////////////////////////////////////////
+		// ADC
+
+		if(sysfs_create_file(g_pKoADC, &g_tivaUVersAtt.attr))
 		{
 			KALERT("sysfs_create_file failed\n");
 			break;
 		}
 
-		if(sysfs_create_file(g_pKoTiva, &g_tivaUV5VsysAtt.attr))
+		if(sysfs_create_file(g_pKoADC, &g_tivaUBatV3Att.attr))
 		{
 			KALERT("sysfs_create_file failed\n");
 			break;
 		}
 
-		if(sysfs_create_file(g_pKoTiva, &g_tivaUV3V6BatAtt.attr))
+		if(sysfs_create_file(g_pKoADC, &g_tivaTempAtt.attr))
 		{
 			KALERT("sysfs_create_file failed\n");
 			break;
 		}
 
-		if(sysfs_create_file(g_pKoTiva, &g_tivaTempTIVAAtt.attr))
+		if(sysfs_create_file(g_pKoADC, &g_tivaUV5VsysAtt.attr))
 		{
 			KALERT("sysfs_create_file failed\n");
 			break;
 		}
 
-		if(sysfs_create_bin_file(g_pKoTiva, &g_tivaAdcBinAtt))
+		if(sysfs_create_file(g_pKoADC, &g_tivaUV3V6BatAtt.attr))
 		{
 			KALERT("sysfs_create_file failed\n");
 			break;
 		}
 
-		g_nCbFwData = 0;
-		if((g_pFwBuffer = (void*)__get_free_pages(GFP_KERNEL, _FIRMWARE_PAGES_COUNT)))
+		if(sysfs_create_file(g_pKoADC, &g_tivaTempTIVAAtt.attr))
 		{
-			if(sysfs_create_bin_file(g_pKoTiva, &g_tivaFirmwareAtt))
-			{
-				KALERT("sysfs_create_file failed\n");
-				break;
-			}
+			KALERT("sysfs_create_file failed\n");
+			break;
+		}
+
+		if(sysfs_create_bin_file(g_pKoADC, &g_tivaAdcBinAtt))
+		{
+			KALERT("sysfs_create_file failed\n");
+			break;
 		}
 
 		/////////////////////////////////////////////////////////////////////
@@ -594,15 +727,17 @@ static int drv_init(void)
 
 		/////////////////////////////////////////////////////////////////////
 
-		init_timer(&g_jiq_timer);
-		g_jiq_timer.function = OnJigTimer;
-		g_jiq_timer.data = 0;
-		g_jiq_timer.expires = _TIMER_INTERVAL;
-		add_timer(&g_jiq_timer);
-		g_bTimerRunning = true;
+		init_timer(&g_timer_list);
+		g_timer_list.function = _WorkScheduler;
+		g_timer_list.data = 0;
+		g_timer_list.expires = _TIMER_INTERVAL;
+		add_timer(&g_timer_list);
+		_SetTimerRunning(true);
 
 		/////////////////////////////////////////////////////////////////////
 
+		_SetSysFsRunning(true);
+
 		if(!queue_work(g_pwq, &g_sysFsWorkObj))
 		{
 			KALERT("%s: queue_work failed\n", __FUNCTION__);
@@ -611,17 +746,19 @@ static int drv_init(void)
 
 		/////////////////////////////////////////////////////////////////////
 
-		KALERT("%s, Ctx: \"%s\"-(%d)\n", __FUNCTION__, current->comm, current->pid);
+		KALERT("%s, Ctx: \"%s\"-(%d), HZ: %d\n", __FUNCTION__, current->comm, current->pid, HZ);
 		return 0;
 	}
 	while(0);
 
 	/////////////////////////////////////////////////////////////////////////
+	
+	_SetSysFsRunning(false);
 
-	if(g_bTimerRunning)
+	if(_GetTimerRunning())
 	{
-		g_bTimerRunning = false;
-		del_timer_sync(&g_jiq_timer);
+		_SetTimerRunning(false);
+		del_timer_sync(&g_timer_list);
 	}
 
 	if(g_pwq)
@@ -630,25 +767,43 @@ static int drv_init(void)
 		g_pwq = NULL;
 	}
 
-	if(g_pFwBuffer)
+	SfAttExit();
+
+	if(g_pKoFirmware)
+	{
+		sysfs_remove_bin_file(g_pKoFirmware, &g_tivaFwImageAtt);
+		sysfs_remove_file(g_pKoFirmware, &g_tivaVersionAtt.attr);
+
+		kobject_put(g_pKoFirmware);
+		g_pKoFirmware = NULL;
+	}
+
+	if(g_pKoADC)
 	{
-		free_pages((unsigned long)g_pFwBuffer, _FIRMWARE_PAGES_COUNT);
-		g_pFwBuffer = NULL;
-		g_nCbFwData = 0;
+		sysfs_remove_file(g_pKoADC, &g_tivaUVersAtt.attr);
+		sysfs_remove_file(g_pKoADC, &g_tivaUBatV3Att.attr);
+		sysfs_remove_file(g_pKoADC, &g_tivaTempAtt.attr);
+		sysfs_remove_file(g_pKoADC, &g_tivaUV5VsysAtt.attr);
+		sysfs_remove_file(g_pKoADC, &g_tivaUV3V6BatAtt.attr);
+		sysfs_remove_file(g_pKoADC, &g_tivaTempTIVAAtt.attr);
+		sysfs_remove_bin_file(g_pKoADC, &g_tivaAdcBinAtt);
+
+		kobject_put(g_pKoADC);
+		g_pKoADC = NULL;
+	}
+
+	if(g_pKoBacklight)
+	{
+		sysfs_remove_file(g_pKoBacklight, &g_tivaBrightnessAtt.attr);
+		sysfs_remove_file(g_pKoBacklight, &g_tivaFrequencyAtt.attr);
+
+		kobject_put(g_pKoBacklight);
+		g_pKoBacklight = NULL;
 	}
 
 	if(g_pKoTiva)
 	{
-		sysfs_remove_file(g_pKoTiva, &g_tivaVersionAtt.attr);
 		sysfs_remove_file(g_pKoTiva, &g_tivaUptimeAtt.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaUVersAtt.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaUBatV3Att.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaTempAtt.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaUV5VsysAtt.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaUV3V6BatAtt.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaTempTIVAAtt.attr);
-		sysfs_remove_bin_file(g_pKoTiva, &g_tivaAdcBinAtt);
-		sysfs_remove_bin_file(g_pKoTiva, &g_tivaFirmwareAtt);
 
 		kobject_put(g_pKoTiva);
 		g_pKoTiva = NULL;
@@ -667,8 +822,13 @@ static int drv_init(void)
 
 static void drv_exit(void)
 {
-	g_bTimerRunning = false;
-	del_timer_sync(&g_jiq_timer);
+	_SetSysFsRunning(false);
+
+	if(_GetTimerRunning())
+	{
+		_SetTimerRunning(false);
+		del_timer_sync(&g_timer_list);
+	}
 
 	if(g_pwq)
 	{
@@ -676,24 +836,43 @@ static void drv_exit(void)
 		g_pwq = NULL;
 	}
 
-	if(g_pFwBuffer)
+	SfAttExit();
+
+	if(g_pKoFirmware)
 	{
-		free_pages((unsigned long)g_pFwBuffer, _FIRMWARE_PAGES_COUNT);
-		g_pFwBuffer = NULL;
-		g_nCbFwData = 0;
+		sysfs_remove_bin_file(g_pKoFirmware, &g_tivaFwImageAtt);
+		sysfs_remove_file(g_pKoFirmware, &g_tivaVersionAtt.attr);
+
+		kobject_put(g_pKoFirmware);
+		g_pKoFirmware = NULL;
+	}
+
+	if(g_pKoADC)
+	{
+		sysfs_remove_file(g_pKoADC, &g_tivaUVersAtt.attr);
+		sysfs_remove_file(g_pKoADC, &g_tivaUBatV3Att.attr);
+		sysfs_remove_file(g_pKoADC, &g_tivaTempAtt.attr);
+		sysfs_remove_file(g_pKoADC, &g_tivaUV5VsysAtt.attr);
+		sysfs_remove_file(g_pKoADC, &g_tivaUV3V6BatAtt.attr);
+		sysfs_remove_file(g_pKoADC, &g_tivaTempTIVAAtt.attr);
+		sysfs_remove_bin_file(g_pKoADC, &g_tivaAdcBinAtt);
+
+		kobject_put(g_pKoADC);
+		g_pKoADC = NULL;
+	}
+
+	if(g_pKoBacklight)
+	{
+		sysfs_remove_file(g_pKoBacklight, &g_tivaBrightnessAtt.attr);
+		sysfs_remove_file(g_pKoBacklight, &g_tivaFrequencyAtt.attr);
+
+		kobject_put(g_pKoBacklight);
+		g_pKoBacklight = NULL;
 	}
 
 	if(g_pKoTiva)
 	{
-		sysfs_remove_file(g_pKoTiva, &g_tivaVersionAtt.attr);
 		sysfs_remove_file(g_pKoTiva, &g_tivaUptimeAtt.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaUVersAtt.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaUBatV3Att.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaTempAtt.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaUV5VsysAtt.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaUV3V6BatAtt.attr);
-		sysfs_remove_file(g_pKoTiva, &g_tivaTempTIVAAtt.attr);
-		sysfs_remove_bin_file(g_pKoTiva, &g_tivaFirmwareAtt);
 
 		kobject_put(g_pKoTiva);
 	}

+ 29 - 0
gfaspi.h

@@ -0,0 +1,29 @@
+// gfaspi.h :
+//
+
+#if !defined(AGD_GFASPI_H__F1751711_2AAA_48F4_9959_E6F56DA316B8__INCLUDED_)
+#define AGD_GFASPI_H__F1751711_2AAA_48F4_9959_E6F56DA316B8__INCLUDED_
+
+#ifdef __cplusplus
+extern "C" {
+#endif	//	__cplusplus
+
+/////////////////////////////////////////////////////////////////////////////
+// gfaspi.h - Declarations:
+
+typedef struct _TIVA_ADC
+{
+	int UVers;
+	int UBatV3;
+	int Temp;
+	int UV5Vsys;
+	int UV3V6Bat;
+	int TempTIVA;
+}TIVA_ADC, *LPTIVA_ADC;
+typedef const TIVA_ADC *LPCTIVA_ADC;
+
+/////////////////////////////////////////////////////////////////////////////
+#ifdef __cplusplus
+}
+#endif	//	__cplusplus
+#endif	//	!defined(AGD_GFASPI_H__F1751711_2AAA_48F4_9959_E6F56DA316B8__INCLUDED_)

+ 101 - 84
kfirmware.c

@@ -1,52 +1,53 @@
-#include <linux/version.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/kobject.h>
-#include <linux/errno.h>
-#include <linux/sysfs.h>
-#include <linux/syscalls.h>
-#include "defines.h"
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kobject.h>
+#include <linux/errno.h>
+#include <linux/sysfs.h>
+#include <linux/syscalls.h>
+#include "defines.h"
 #include "kfirmware.h"
 #include "sfsattrib.h"
+#include "ksync.h"
 
 /////////////////////////////////////////////////////////////////////////////
-
-static unsigned int g_pdw32CRC32Table[] =
-{
-	0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
-	0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
-	0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
-	0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
-	0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
-	0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
-	0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
-	0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
-	0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
-	0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
-	0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
-	0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
-	0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
-	0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
-	0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
-	0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
-	0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
-	0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
-	0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
-	0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
-	0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
-	0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
-	0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
-	0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
-	0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
-	0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
-	0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
-	0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
-	0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
-	0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
-	0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
-	0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
-};
+
+static unsigned int g_pdw32CRC32Table[] =
+{
+	0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+	0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+	0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+	0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+	0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+	0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+	0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+	0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+	0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+	0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+	0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+	0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+	0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+	0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+	0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+	0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+	0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+	0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+	0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+	0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+	0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+	0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+	0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+	0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+	0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+	0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+	0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+	0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+	0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+	0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+	0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+	0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
 
 static TIVA_UPLOAD_INFO g_tui;
 
@@ -113,38 +114,39 @@ bool KfwMatchMaterialNum(const char *pszMatNumEEPROM, const char *pszMatNumImg)
 }
 
 /////////////////////////////////////////////////////////////////////////////
-
-LPCKFW_IMG_HEADER KfwLookupImgHeader(const void *pData, size_t nCbData)
-{
-	int i;
-	const unsigned int *pImg = (const unsigned int*)pData;
-
-	if(nCbData > (257 * sizeof(unsigned int)))
-	{
-		for(i = 0; i < 257; ++i, nCbData -= sizeof(unsigned int))
-		{
-			LPKFW_IMG_HEADER paih = (LPKFW_IMG_HEADER)pImg++;
-
-			if(	(paih->nPrefix0 == KFW_IMG_HEADER_PREFIX_0) &&
-				(paih->nPrefix1 == KFW_IMG_HEADER_PREFIX_1))
-			{
-				if(nCbData >= sizeof(KFW_IMG_HEADER))
-					return paih;
-				break;
-			}
-		}
-	}
-
-	return NULL;
-}
+
+LPCKFW_IMG_HEADER KfwLookupImgHeader(const void *pData, size_t nCbData)
+{
+	int i;
+	const unsigned int *pImg = (const unsigned int*)pData;
+
+	if(nCbData > (257 * sizeof(unsigned int)))
+	{
+		for(i = 0; i < 257; ++i, nCbData -= sizeof(unsigned int))
+		{
+			LPKFW_IMG_HEADER paih = (LPKFW_IMG_HEADER)pImg++;
+
+			if(	(paih->nPrefix0 == KFW_IMG_HEADER_PREFIX_0) &&
+				(paih->nPrefix1 == KFW_IMG_HEADER_PREFIX_1))
+			{
+				if(nCbData >= sizeof(KFW_IMG_HEADER))
+					return paih;
+				break;
+			}
+		}
+	}
+
+	return NULL;
+}
 
 /////////////////////////////////////////////////////////////////////////////
 
 int KfwOnDataDropped(const void *pData, size_t nCbData, LPKFW_DROP_CTX pdc)
 {
-	mutex_lock(&g_mutex);
-	memset(&g_tui, 0, sizeof(g_tui));
-	mutex_unlock(&g_mutex);
+//	ksync_lock();
+//	memset(&g_tui, 0, sizeof(g_tui));
+//	ksync_unlock();
+	atomic_set(&g_tui.flgUIReady, 0);
 
 	if(nCbData > (257 * sizeof(unsigned int)))
 	{
@@ -163,8 +165,8 @@ int KfwOnDataDropped(const void *pData, size_t nCbData, LPKFW_DROP_CTX pdc)
 		if(nCbData == pdc->pkih->nImgLength)
 		{
 			dwCRC32 = _CalcImgCRC32(pData, pdc->pkih);
-//			KALERT("%s: DataLen: %zu, ImgLen: %zu\n", __FUNCTION__, nCbData, pdc->pkih->nImgLength);
-//			KALERT("%s: DataCRC: %08X, ImgCRC: %08X\n", __FUNCTION__, dwCRC32, pdc->pkih->nImgCRC32);
+			KALERT("%s: DataLen: %zu, ImgLen: %zu\n", __FUNCTION__, nCbData, pdc->pkih->nImgLength);
+			KALERT("%s: DataCRC: %08X, ImgCRC: %08X\n", __FUNCTION__, dwCRC32, pdc->pkih->nImgCRC32);
 			
 			if(pdc->pkih->nImgCRC32 != dwCRC32)
 			{
@@ -172,8 +174,8 @@ int KfwOnDataDropped(const void *pData, size_t nCbData, LPKFW_DROP_CTX pdc)
 				return -EPERM;
 			}
 
-			nOffsetMat = (ssize_t)pdc->pkih->app.pszImgMaterialNum - KFW_DEFAULT_BASE_ADDRESS;
-			nOffsetBld = (ssize_t)pdc->pkih->app.pszImgNameBuild   - KFW_DEFAULT_BASE_ADDRESS;
+			nOffsetMat = (ssize_t)pdc->pkih->app.pszImgMaterialNum;// - KFW_DEFAULT_BASE_ADDRESS;
+			nOffsetBld = (ssize_t)pdc->pkih->app.pszImgNameBuild;//   - KFW_DEFAULT_BASE_ADDRESS;
 
 			if(	(nOffsetMat > 0) && (((size_t)nOffsetMat + KFW_MAX_IMG_MATERIAL_NUM_LENGTH) <= nCbData) &&
 				(nOffsetBld > 0) && (((size_t)nOffsetBld + KFW_MAX_IMG_NAME_BUILD_LENGTH) <= nCbData))
@@ -181,21 +183,27 @@ int KfwOnDataDropped(const void *pData, size_t nCbData, LPKFW_DROP_CTX pdc)
 				const char *pszMat = ((const char*)pData) + nOffsetMat;
 				const char *pszBld = ((const char*)pData) + nOffsetBld;
 
-//				KALERT("%s: Material-Nr.: %s\n", __FUNCTION__, pszMat);
-//				KALERT("%s: Build-Nr.:    %s\n", __FUNCTION__, pszBld);
+				KALERT("%s: Material-Nr.: %s\n", __FUNCTION__, pszMat);
+				KALERT("%s: Build-Nr.:    %s\n", __FUNCTION__, pszBld);
 
 				SfAttLockFirmware(true);
 
-				mutex_lock(&g_mutex);
+				ksync_lock();
 				g_tui.pData		= pData;
 				g_tui.nCbData	= nCbData;
 				g_tui.pkih		= pdc->pkih;
 				g_tui.pszMat	= pszMat;
 				g_tui.pszBld	= pszBld;
-				mutex_unlock(&g_mutex);
-				
+				ksync_unlock();
+
+				atomic_set(&g_tui.flgUIReady, 1);
+				KALERT("%s: Image ready for upload!\n", __FUNCTION__);
 				return 1;
 			}
+			else
+			{
+				KALERT("%s: Offs.Mat: %zd, Offs.Build: %zd, ImgLength: %zu\n", __FUNCTION__, nOffsetMat, nOffsetBld, nCbData);
+			}
 		}
 		else if(nCbData > pdc->pkih->nImgLength)
 		{
@@ -209,19 +217,28 @@ int KfwOnDataDropped(const void *pData, size_t nCbData, LPKFW_DROP_CTX pdc)
 
 /////////////////////////////////////////////////////////////////////////////
 
+bool KfwUploadInfoReady(void)
+{
+	return !!atomic_read(&g_tui.flgUIReady);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
 bool KfwQueryUploadInfo(LPTIVA_UPLOAD_INFO ptui)
 {
 	if(ptui)
 	{
 		bool bRet;
-		mutex_lock(&g_mutex);
+		ksync_lock();
 		memcpy(ptui, &g_tui, sizeof(g_tui));
-		mutex_unlock(&g_mutex);
+		ksync_unlock();
 		if((bRet = !!ptui->pData && !!ptui->pkih && !!ptui->nCbData))
+		{
 			memset(&g_tui, 0, sizeof(g_tui));
+			atomic_set(&g_tui.flgUIReady, 0);
+		}
 		return bRet;
 	}
 
 	return false;
 }
-

+ 1 - 0
kfirmware.h

@@ -23,6 +23,7 @@ bool KfwMatchMaterialNum(const char *pszMatNumEEPROM, const char *pszMatNumImg);
 LPCKFW_IMG_HEADER KfwLookupImgHeader(const void *pData, size_t nCbData);
 int KfwOnDataDropped(const void *pData, size_t nCbData, LPKFW_DROP_CTX pdc);
 bool KfwQueryUploadInfo(LPTIVA_UPLOAD_INFO ptui);
+bool KfwUploadInfoReady(void);
 
 /////////////////////////////////////////////////////////////////////////////
 #ifdef __cplusplus

+ 89 - 9
kspi.c

@@ -102,9 +102,9 @@ int kspi_tx(struct file *pf, const void *pData, size_t nCbData)
 		.tx_buf			= (unsigned long)pData,
 		.rx_buf			= 0,
 		.len			= nCbData,
-		.delay_usecs	= 0,
-		.speed_hz		= _SPI_SPEED_HZ,
-		.bits_per_word	= _SPI_BITS_PER_WORD,
+//		.delay_usecs	= 0,
+//		.speed_hz		= _SPI_SPEED_HZ,
+//		.bits_per_word	= _SPI_BITS_PER_WORD,
 	};
 
 	if((ret = kf_ioctl(pf, SPI_IOC_MESSAGE(1), (unsigned long)&tr)) < 0)
@@ -123,9 +123,9 @@ int kspi_rx(struct file *pf, void *pData, size_t nCbData)
 		.tx_buf			= 0,
 		.rx_buf			= (unsigned long)pData,
 		.len			= nCbData,
-		.delay_usecs	= 0,
-		.speed_hz		= _SPI_SPEED_HZ,
-		.bits_per_word	= _SPI_BITS_PER_WORD,
+//		.delay_usecs	= 0,
+//		.speed_hz		= _SPI_SPEED_HZ,
+//		.bits_per_word	= _SPI_BITS_PER_WORD,
 	};
 
 	if((ret = kf_ioctl(pf, SPI_IOC_MESSAGE(1), (unsigned long)&tr)) < 0)
@@ -144,9 +144,9 @@ int kspi_tx_rx(struct file *pf, const void *pTx, void *pRx, size_t nCb)
 		.tx_buf			= (unsigned long)pTx,
 		.rx_buf			= (unsigned long)pRx,
 		.len			= nCb,
-		.delay_usecs	= 0,
-		.speed_hz		= _SPI_SPEED_HZ,
-		.bits_per_word	= _SPI_BITS_PER_WORD,
+//		.delay_usecs	= 0,
+//		.speed_hz		= _SPI_SPEED_HZ,
+//		.bits_per_word	= _SPI_BITS_PER_WORD,
 	};
 
 	if((ret = kf_ioctl(pf, SPI_IOC_MESSAGE(1), (unsigned long)&tr)) < 0)
@@ -174,3 +174,83 @@ int kspi_tx_rx_byte(struct file *pf, unsigned char tx, unsigned char *rx)
 {
 	return kspi_tx_rx(pf, &tx, rx, 1);
 }
+
+/////////////////////////////////////////////////////////////////////////////
+
+bool KSpiInit(struct file *pf)
+{
+	bool bRet		= false;
+	uint8_t mode	= 0;
+	uint8_t bits	= 0;
+	uint32_t speed	= 0;
+
+	do
+	{
+		if(kspi_write_mode(pf, SPI_MODE_3) < 0)
+		{
+			KALERT("%s: kspi_write_mode failed!\n", __FUNCTION__);
+			break;
+		}
+
+		if(kspi_read_mode(pf, &mode) < 0)
+		{
+			KALERT("%s: kspi_read_mode failed!\n", __FUNCTION__);
+			break;
+		}
+
+		if(mode != SPI_MODE_3)
+		{
+			KALERT("%s: Invalid mode!\n", __FUNCTION__);
+			break;
+		}
+
+		/////////////////////////////////////////////////////////////////
+
+		if(kspi_write_bits_per_word(pf, _SPI_BITS_PER_WORD) < 0)
+		{
+			KALERT("%s: kspi_write_bits_per_word failed!\n", __FUNCTION__);
+			break;
+		}
+
+		if(kspi_read_bits_per_word(pf, &bits) < 0)
+		{
+			KALERT("%s: kspi_read_bits_per_word failed!\n", __FUNCTION__);
+			break;
+		}
+
+		if(bits != _SPI_BITS_PER_WORD)
+		{
+			KALERT("%s: Invalid bits per word!\n", __FUNCTION__);
+			break;
+		}
+
+		/////////////////////////////////////////////////////////////////
+
+		if(kspi_write_max_speed_hz(pf, _SPI_SPEED_HZ) < 0)
+		{
+			KALERT("%s: kspi_write_max_speed_hz failed!\n", __FUNCTION__);
+			break;
+		}
+
+		if(kspi_read_max_speed_hz(pf, &speed) < 0)
+		{
+			KALERT("%s: kspi_read_max_speed_hz failed!\n", __FUNCTION__);
+			break;
+		}
+
+		if(speed != _SPI_SPEED_HZ)
+		{
+			KALERT("%s: Invalid max. speed!\n", __FUNCTION__);
+			break;
+		}
+
+		bRet = true;
+	}
+	while(false);
+
+	return bRet;
+}
+
+void KSpiExit(void)
+{
+}

+ 5 - 0
kspi.h

@@ -32,6 +32,11 @@ int kspi_rx_byte	(struct file *pf, unsigned char *rx);
 int kspi_tx_byte	(struct file *pf, unsigned char tx);
 int kspi_tx_rx_byte	(struct file *pf, unsigned char tx, unsigned char *rx);
 
+/////////////////////////////////////////////////////////////////////////////
+
+bool KSpiInit(struct file *pf);
+void KSpiExit(void);
+
 /////////////////////////////////////////////////////////////////////////////
 #ifdef __cplusplus
 }

+ 44 - 0
ksync.c

@@ -0,0 +1,44 @@
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/mutex.h>
+#include <linux/errno.h>
+#include "defines.h"
+#include "ksync.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+static DEFINE_MUTEX(g_mutex);
+
+/////////////////////////////////////////////////////////////////////////////
+
+void ksync_lock(void)
+{
+	mutex_lock(&g_mutex);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void ksync_unlock(void)
+{
+	mutex_unlock(&g_mutex);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int ksync_sleep_jiffies(long jiffies)
+{
+	if(jiffies <= 0)
+		return 0;
+	set_current_state(TASK_INTERRUPTIBLE); // may return early if a signal is delivered to the current task
+	return schedule_timeout(jiffies);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int ksync_sleep_ms(long ms)
+{
+	return ksync_sleep_jiffies(msecs_to_jiffies(ms));
+}

+ 23 - 0
ksync.h

@@ -0,0 +1,23 @@
+// ksync.h :
+//
+
+#if !defined(AGD_KSYNC_H__180EAA78_04DF_4F7B_88DC_E8D432A809D4__INCLUDED_)
+#define AGD_KSYNC_H__180EAA78_04DF_4F7B_88DC_E8D432A809D4__INCLUDED_
+
+#ifdef __cplusplus
+extern "C" {
+#endif	//	__cplusplus
+
+/////////////////////////////////////////////////////////////////////////////
+// ksync.h - Declarations:
+
+void ksync_lock(void);
+void ksync_unlock(void);
+int ksync_sleep_jiffies(long jiffies);
+int ksync_sleep_ms(long ms);
+
+/////////////////////////////////////////////////////////////////////////////
+#ifdef __cplusplus
+}
+#endif	//	__cplusplus
+#endif	//	!defined(AGD_KSYNC_H__180EAA78_04DF_4F7B_88DC_E8D432A809D4__INCLUDED_)

+ 91 - 19
ktiva.c

@@ -1,6 +1,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include "ktiva.h"
+#include "ksync.h"
 
 /////////////////////////////////////////////////////////////////////////////
 
@@ -65,11 +66,18 @@ int ktiva_wait_ack(struct file *pf)
 {
 	int ret, i = 0;
 	unsigned char c = 0;
-//    unsigned long start = jiffies;
+#if _SITARA_EGGELSBERG
+    unsigned long start = jiffies;
+    unsigned long timeout = jiffies + 4;
+#else	//	_SITARA_EGGELSBERG
     unsigned long timeout = jiffies + 2 *HZ; // 2 sec. timeout
+#endif	//	_SITARA_EGGELSBERG
 
 	while(c != CMD_ACK)
 	{
+		++i;
+		ksync_sleep_jiffies(1);
+
 		if((ret = kspi_rx_byte(pf, &c)) < 0)
 			return ret;
 		else if(c == CMD_NAK)
@@ -79,20 +87,17 @@ int ktiva_wait_ack(struct file *pf)
 		}
 		else if(c != CMD_ACK)
 		{
-			++i;
-
 			if(time_is_before_eq_jiffies(timeout))
 			{
 				KALERT("%s: timeout!\n", __FUNCTION__);
 				return -ETIME;
 			}
-
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
 		}
 	}
 
-//	KALERT("ktiva_wait_ack: jiffies: %lu, loops: %d\n", ((long)jiffies - (long)start), i);
+#if _SITARA_EGGELSBERG
+	KALERT("ktiva_wait_ack: jiffies: %lu, loops: %d\n", ((long)jiffies - (long)start), i);
+#endif	//	_SITARA_EGGELSBERG
 	return (c == CMD_ACK) ? 0 : -1;
 }
 
@@ -161,8 +166,7 @@ int ktiva_recv_frame(struct file *pf, unsigned char cmd, void *pData, size_t nCb
 
 		if(!len)
 		{
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			ksync_sleep_jiffies(1);
 
 			if(time_is_before_eq_jiffies(timeout))
 			{
@@ -193,7 +197,7 @@ int ktiva_recv_frame(struct file *pf, unsigned char cmd, void *pData, size_t nCb
 	}
 	else if(buf[1] != cmd)
 	{
-		KALERT("%s: invalid command: %hhu!\n", __FUNCTION__, buf[1]);
+		KALERT("%s: invalid command: %02hhX!\n", __FUNCTION__, buf[1]);
 		return -EPROTO;
 	}
 
@@ -206,7 +210,12 @@ int ktiva_recv_frame(struct file *pf, unsigned char cmd, void *pData, size_t nCb
 
 	if(buf[0] != chk)
 	{
-		KALERT("%s: checksum error: recv: %02hhX, calc: %02hhX!\n", __FUNCTION__, buf[0], chk);
+		KALERT("%s: checksum err: [l=%hhu, c=0x%02hhX], recv: 0x%02hhX, calc: 0x%02hhX!\n", __FUNCTION__, len, buf[1], buf[0], chk);
+#if 1
+		for(i = 2; i < ret; ++i)
+			KALERT("%02hhX ", buf[i]);
+		KALERT("\n");
+#endif	//	_SITARA_EGGELSBERG
 		return -EPROTO;
 	}
 
@@ -242,8 +251,7 @@ int ktiva_recv_bootloader_frame(struct file *pf, unsigned char cmd, void *pData,
 
 		if(!len)
 		{
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			ksync_sleep_jiffies(1);
 
 			if(time_is_before_eq_jiffies(timeout))
 			{
@@ -254,7 +262,7 @@ int ktiva_recv_bootloader_frame(struct file *pf, unsigned char cmd, void *pData,
 	}
 	while(!len);
 
-	if(len > (int)(nCbData + 3))
+	if(len > (int)(nCbData + 2))
 	{
 		KALERT("%s: Insufficient buffer length: %zu - need %hhu!\n", __FUNCTION__, nCbData, len - 3);
 		return -ENOMEM;
@@ -280,7 +288,7 @@ int ktiva_recv_bootloader_frame(struct file *pf, unsigned char cmd, void *pData,
 
 	if(buf[0] != chk)
 	{
-		KALERT("%s: checksum error: recv: %02hhX, calc: %02hhX!\n", __FUNCTION__, buf[0], chk);
+		KALERT("%s: checksum error: recv: 0x%02hhX, calc: 0x%02hhX!\n", __FUNCTION__, buf[0], chk);
 		return -EPROTO;
 	}
 
@@ -315,8 +323,7 @@ int TivaRevive(struct file *pf)
 
 		if(i && !(i % 8))
 		{
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			ksync_sleep_jiffies(1);
 		}
 	}
 
@@ -602,8 +609,13 @@ int TivaCmdStartDownload(struct file *pf, unsigned int addr, size_t size)
 {
     int ret;
     unsigned int data[2] = {cpu_to_be32(addr), cpu_to_be32((unsigned int)size)};
+	KALERT("%s: Addr.: 0x%08X, CB: %zu!\n", __FUNCTION__, addr, size);
 
-    if((ret = ktiva_send_frame(pf, COMMAND_DOWNLOAD, data, sizeof(data))) != sizeof(data))
+    if((ret = ktiva_send_frame(pf, COMMAND_DOWNLOAD, data, sizeof(data))) == sizeof(data))
+    {
+    	ret = 0;
+    }
+    else
     {
 		KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret);
     }
@@ -616,8 +628,13 @@ int TivaCmdStartDownload(struct file *pf, unsigned int addr, size_t size)
 int TivaCmdSendDataBlock(struct file *pf, const void *pBlock, size_t nCbBlock)
 {
     int ret;
+//	KALERT("%s: Data: 0x%p, CB: %zu!\n", __FUNCTION__, pBlock, nCbBlock);
 
-    if((ret = ktiva_send_frame(pf, COMMAND_DOWNLOAD, pBlock, nCbBlock)) != nCbBlock)
+    if((ret = ktiva_send_frame(pf, COMMAND_SEND_DATA, pBlock, nCbBlock)) == nCbBlock)
+    {
+    	ret = 0;
+    }
+    else
     {
 		KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret);
     }
@@ -638,3 +655,58 @@ int TivaCmdReset(struct file *pf)
 
     return ret;
 }
+
+/////////////////////////////////////////////////////////////////////////////
+
+int TivaCmdGetMatSer(struct file *pf, LPTIVA_MAT_SER pms)
+{
+    int ret;
+    TIVA_MAT_SER data;
+
+#if _EXTENDED_ERROR_CHECK
+	if(!pms)
+	{
+		KALERT("%s: Invalid data pointer!\n", __FUNCTION__);
+		return -EINVAL;
+	}
+#endif	//	_EXTENDED_ERROR_CHECK
+
+    if((ret = ktiva_send_frame(pf, COMMAND_GET_MAT_SER, NULL, 0)) == 0)
+	{
+		if((ret = ktiva_recv_bootloader_frame(pf, COMMAND_GET_MAT_SER, &data, sizeof(data))) == sizeof(data))
+        {
+        	memcpy(pms, &data, sizeof(data));
+			kspi_tx_byte(pf, CMD_ACK);
+            ret = 0;
+        }
+        else
+        {
+            KALERT("%s - ktiva_recv_frame failed: %d\n", __FUNCTION__, ret);
+        }
+    }
+    else
+    {
+		KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret);
+    }
+
+    return ret;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int TivaCmdSetBacklight(struct file *pf, unsigned int nFrequency, unsigned int nBrightness)
+{
+    int ret;
+    unsigned int data[2] = {cpu_to_be32(nFrequency), cpu_to_be32(nBrightness * 10)};
+
+    if((ret = ktiva_send_frame(pf, COMMAND_SET_BACKLIGHT, data, sizeof(data))) == sizeof(data))
+    {
+    	ret = 0;
+    }
+    else
+    {
+		KALERT("%s - ktiva_send_frame failed: %d!\n", __FUNCTION__, ret);
+    }
+
+    return ret;
+}

+ 4 - 1
ktiva.h

@@ -37,7 +37,8 @@ extern "C" {
 #define COMMAND_GET_ADC								0x5A
 #define COMMAND_SET_BACKLIGHT						0x5B
 #define COMMAND_GET_UPTIME							0x5C
-//#define COMMAND_GET_MATERIAL_SERIAL_ID				0x5D
+#define COMMAND_SET_MAT_SER							0x5D
+#define COMMAND_GET_MAT_SER							0x5E
 
 #define COMMAND_RET_SUCCESS							0x40
 #define COMMAND_RET_UNKNOWN_CMD						0x41
@@ -71,6 +72,8 @@ int TivaCmdStartDownload		(struct file *pf, unsigned int addr, size_t size);
 int TivaCmdSendDataBlock		(struct file *pf, const void *pBlock, size_t nCbBlock);
 int TivaCmdReset				(struct file *pf);
 int TivaRevive					(struct file *pf);
+int TivaCmdGetMatSer			(struct file *pf, LPTIVA_MAT_SER pms);
+int TivaCmdSetBacklight			(struct file *pf, unsigned int nFrequency, unsigned int nBrightness);
 
 /////////////////////////////////////////////////////////////////////////////
 #ifdef __cplusplus

+ 189 - 41
sfsattrib.c

@@ -9,39 +9,53 @@
 #include "defines.h"
 #include "sfsattrib.h"
 #include "kfirmware.h"
+#include "ksync.h"
 
 /////////////////////////////////////////////////////////////////////////////
 
 int g_hw = -1, g_sw = -1;
 TIVA_ADC g_tadc;
 unsigned long long g_nUpTime = 0;
-void *g_pFwBuffer = NULL;
-size_t g_nCbFwData = 0;
 
-static bool g_bFwWriteLock = false;
-DEFINE_MUTEX(g_mutex);
+static void *g_pFwBuffer	= NULL;
+static size_t g_nCbFwData	= 0;
+
+static atomic_t g_flgFwLocked;
+static atomic_t g_flgBacklightChanged;
+static atomic_t g_valBacklightBrightness;
+static atomic_t g_valBacklightFrequency;
 
 /////////////////////////////////////////////////////////////////////////////
 
 static ssize_t version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
-	if(g_hw < 0 || g_sw < 0)
-		return -ENODATA;
-	return sprintf(buf, "%d %d", g_hw, g_sw);
+	int hw, sw;
+	ksync_lock();
+	hw = g_hw;
+	sw = g_sw;
+	ksync_unlock();
+	return sprintf(buf, "%d %d", hw, sw);
 }
 
 /////////////////////////////////////////////////////////////////////////////
 
-static ssize_t Uptime_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+static ssize_t uptime_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%llu", g_nUpTime);
+	unsigned long long nVal;
+	ksync_lock();
+	nVal = g_nUpTime;
+	ksync_unlock();
+	return sprintf(buf, "%llu", nVal);
 }
 
 /////////////////////////////////////////////////////////////////////////////
 
 static ssize_t UVers_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
-	int nVal = g_tadc.UVers + 40;
+	int nVal;
+	ksync_lock();
+	nVal = g_tadc.UVers + 40;
+	ksync_unlock();
 	return sprintf(buf, "%d.%02d", nVal / 100, nVal % 100);
 }
 
@@ -49,7 +63,10 @@ static ssize_t UVers_show(struct kobject *kobj, struct kobj_attribute *attr, cha
 
 static ssize_t UBatV3_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
-	int nVal = g_tadc.UBatV3;
+	int nVal;
+	ksync_lock();
+	nVal = g_tadc.UBatV3;
+	ksync_unlock();
 	return sprintf(buf, "%d.%02d", nVal / 100, nVal % 100);
 }
 
@@ -57,7 +74,10 @@ static ssize_t UBatV3_show(struct kobject *kobj, struct kobj_attribute *attr, ch
 
 static ssize_t TempBoard_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
-	int nVal = g_tadc.Temp;
+	int nVal;
+	ksync_lock();
+	nVal = g_tadc.Temp;
+	ksync_unlock();
 	return sprintf(buf, "%d.%d0", nVal / 10, nVal % 10);
 }
 
@@ -65,7 +85,10 @@ static ssize_t TempBoard_show(struct kobject *kobj, struct kobj_attribute *attr,
 
 static ssize_t UV5Vsys_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
-	int nVal = g_tadc.UV5Vsys;
+	int nVal;
+	ksync_lock();
+	nVal = g_tadc.UV5Vsys;
+	ksync_unlock();
 	return sprintf(buf, "%d.%02d", nVal / 100, nVal % 100);
 }
 
@@ -73,7 +96,10 @@ static ssize_t UV5Vsys_show(struct kobject *kobj, struct kobj_attribute *attr, c
 
 static ssize_t UV3V6Bat_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
-	int nVal = g_tadc.UV3V6Bat;
+	int nVal;
+	ksync_lock();
+	nVal = g_tadc.UV3V6Bat;
+	ksync_unlock();
 	return sprintf(buf, "%d.%02d", nVal / 100, nVal % 100);
 }
 
@@ -81,7 +107,10 @@ static ssize_t UV3V6Bat_show(struct kobject *kobj, struct kobj_attribute *attr,
 
 static ssize_t TempTIVA_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
-	long nVal = 14750 - 18750 * g_tadc.TempTIVA / 4096;
+	long nVal;
+	ksync_lock();
+	nVal = 14750 - 18750 * g_tadc.TempTIVA / 4096;
+	ksync_unlock();
 	return sprintf(buf, "%ld.%02ld", nVal / 100, nVal % 100);
 }
 
@@ -94,16 +123,61 @@ static ssize_t AdcBin_read(struct file *pf, struct kobject *kobj, struct bin_att
 	if((len + off) > sizeof(g_tadc))
 		len = sizeof(g_tadc) - off;
 
-	mutex_lock(&g_mutex);
+	ksync_lock();
 	memcpy(buf, ((const unsigned char*)&g_tadc) + off, len);
-	mutex_unlock(&g_mutex);
-//	KALERT("%s buf: %p, off: %lld, len: %zu\n", __FUNCTION__, buf, off, len);
+	ksync_unlock();
 	return (ssize_t)len;
 }
 
 /////////////////////////////////////////////////////////////////////////////
 
-static ssize_t firmware_read(struct file *pf, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t len)
+static ssize_t brightness_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	ssize_t ret = -EINVAL;
+	if(buf && count)
+	{
+		char szBuf[32];
+		long long val;
+		if(count >= sizeof(szBuf))
+			return -ENOMEM;
+		memcpy(szBuf, buf, count);
+		szBuf[count] = '\0';
+		if(!(ret = kstrtoll(szBuf, 10, &val)))
+		{
+			SfAttSetBacklightBrightness(val);
+			atomic_set(&g_flgBacklightChanged, 1);
+			ret = count;
+		}
+	}
+	return ret;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static ssize_t frequency_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	ssize_t ret = -EINVAL;
+	if(buf && count)
+	{
+		char szBuf[32];
+		long long val;
+		if(count >= sizeof(szBuf))
+			return -ENOMEM;
+		memcpy(szBuf, buf, count);
+		szBuf[count] = '\0';
+		if(!(ret = kstrtoll(szBuf, 10, &val)))
+		{
+			SfAttSetBacklightFrequency(val);
+			atomic_set(&g_flgBacklightChanged, 1);
+			ret = count;
+		}
+	}
+	return ret;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static ssize_t image_read(struct file *pf, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t len)
 {
 	return -EACCES;
 /*	if(off >= g_nCbFwData)
@@ -111,15 +185,15 @@ static ssize_t firmware_read(struct file *pf, struct kobject *kobj, struct bin_a
 	if((off + len) > g_nCbFwData)
 		len = g_nCbFwData - off;
 
-	mutex_lock(&g_mutex);
+	ksync_lock();
 	memcpy(buf, ((char*)g_pFwBuffer) + off, len);
-	mutex_unlock(&g_mutex);
+	ksync_unlock();
 
 	KALERT("%s buf: %p, off: %lld, len: %zu\n", __FUNCTION__, buf, off, len);
 	return len;*/
 }
 
-static ssize_t firmware_write(struct file *pf, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t len)
+static ssize_t image_write(struct file *pf, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t len)
 {
 	int nRet;
 	size_t nCbUbound;
@@ -139,34 +213,34 @@ static ssize_t firmware_write(struct file *pf, struct kobject *kobj, struct bin_
 	if(off == 0) // first block of data
 	{
 		memset(&dctx, 0, sizeof(dctx));
-		mutex_lock(&g_mutex);
+		ksync_lock();
 		g_nCbFwData = 0;
 		memset(g_pFwBuffer, 0xFF, _FIRMWARE_BUFFER_SIZE);
-		mutex_unlock(&g_mutex);
+		ksync_unlock();
 	}
 
 	nCbUbound = off + len;
 
-	mutex_lock(&g_mutex);
+	ksync_lock();
 	memcpy(((char*)g_pFwBuffer) + off, buf, len);
 	if(g_nCbFwData < nCbUbound)
 		g_nCbFwData = nCbUbound;
-	mutex_unlock(&g_mutex);
+	ksync_unlock();
 	
 	if((nRet = KfwOnDataDropped(g_pFwBuffer, g_nCbFwData, &dctx)) < 0)
 	{
-		mutex_lock(&g_mutex);
+		ksync_lock();
 		g_nCbFwData = 0;
-		mutex_unlock(&g_mutex);
+		ksync_unlock();
 		memset(&dctx, 0, sizeof(dctx));
 		SfAttLockFirmware(false);
 		return nRet;
 	}
 	else if(nRet > 0)
 	{
-		mutex_lock(&g_mutex);
+		ksync_lock();
 		g_nCbFwData = 0;
-		mutex_unlock(&g_mutex);
+		ksync_unlock();
 		memset(&dctx, 0, sizeof(dctx));
 	}
 
@@ -174,29 +248,101 @@ static ssize_t firmware_write(struct file *pf, struct kobject *kobj, struct bin_
 	return len;
 }
 
+bool SfAttInit(void)
+{
+	g_nCbFwData = 0;
+	atomic_set(&g_flgBacklightChanged, 0);
+	SfAttSetBacklightBrightness(_BACKLIGHT_DEF_BRIGHT_PERC);
+	SfAttSetBacklightFrequency(_BACKLIGHT_DEF_FREQ_HZ);
+	g_pFwBuffer = (void*)__get_free_pages(GFP_KERNEL, _FIRMWARE_PAGES_COUNT);
+	return !!g_pFwBuffer;
+}
+
+void SfAttExit(void)
+{
+	g_nCbFwData = 0;
+	if(g_pFwBuffer)
+	{
+		free_pages((unsigned long)g_pFwBuffer, _FIRMWARE_PAGES_COUNT);
+		g_pFwBuffer = NULL;
+	}
+}
+
 /////////////////////////////////////////////////////////////////////////////
 
 bool SfAttIsFirmwareLocked(void)
 {
-	bool bRet;
-	mutex_lock(&g_mutex);
-	bRet = g_bFwWriteLock;
-	mutex_unlock(&g_mutex);
-	return bRet;
+	return !!atomic_read(&g_flgFwLocked);
 }
 
 /////////////////////////////////////////////////////////////////////////////
 
 void SfAttLockFirmware(bool bLock)
 {
-	mutex_lock(&g_mutex);
-	g_bFwWriteLock = bLock;
-	mutex_unlock(&g_mutex);
+	atomic_set(&g_flgFwLocked, bLock ? 1 : 0);
 }
 
 /////////////////////////////////////////////////////////////////////////////
 
-struct kobj_attribute g_tivaVersionAtt	= __ATTR_RO(version);
+unsigned int SfAttGetBacklightBrightness(void)
+{
+	return (unsigned int)atomic_read(&g_valBacklightBrightness);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void SfAttSetBacklightBrightness(int val)
+{
+	if(val < 0)
+		val = 0;
+	else if(val > 100)
+		val = 100;
+	atomic_set(&g_valBacklightBrightness, val);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+unsigned int SfAttGetBacklightFrequency(void)
+{
+	return (unsigned int)atomic_read(&g_valBacklightFrequency);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void SfAttSetBacklightFrequency(int val)
+{
+	if(val < _BACKLIGHT_FREQ_MIN_HZ)
+		val = _BACKLIGHT_FREQ_MIN_HZ;
+	else if(val > _BACKLIGHT_FREQ_MAX_HZ)
+		val = _BACKLIGHT_FREQ_MAX_HZ;
+	atomic_set(&g_valBacklightFrequency, val);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+bool SfAttBacklightChanged(void)
+{
+	bool ret = !!atomic_read(&g_flgBacklightChanged);
+	if(ret)
+		atomic_set(&g_flgBacklightChanged, 0);
+	return ret;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// tiva generic
+
+struct kobj_attribute g_tivaUptimeAtt	= __ATTR_RO(uptime);
+
+/////////////////////////////////////////////////////////////////////////////
+// backlight
+
+struct kobj_attribute g_tivaBrightnessAtt	= __ATTR_WO(brightness);
+struct kobj_attribute g_tivaFrequencyAtt	= __ATTR_WO(frequency);
+
+/////////////////////////////////////////////////////////////////////////////
+// ADC
 
 struct kobj_attribute g_tivaUVersAtt	= __ATTR_RO(UVers);
 struct kobj_attribute g_tivaUBatV3Att	= __ATTR_RO(UBatV3);
@@ -206,6 +352,8 @@ struct kobj_attribute g_tivaUV3V6BatAtt	= __ATTR_RO(UV3V6Bat);
 struct kobj_attribute g_tivaTempTIVAAtt	= __ATTR_RO(TempTIVA);
 struct bin_attribute g_tivaAdcBinAtt	= __BIN_ATTR_RO(AdcBin, sizeof(TIVA_ADC));
 
-struct kobj_attribute g_tivaUptimeAtt	= __ATTR_RO(Uptime);
+/////////////////////////////////////////////////////////////////////////////
+// tiva firmware
 
-struct bin_attribute g_tivaFirmwareAtt	= __BIN_ATTR_RW(firmware, 0);
+struct kobj_attribute g_tivaVersionAtt	= __ATTR_RO(version);
+struct bin_attribute g_tivaFwImageAtt	= __BIN_ATTR_RW(image, 0);

+ 13 - 4
sfsattrib.h

@@ -17,9 +17,7 @@ extern "C" {
 extern int g_hw, g_sw;
 extern TIVA_ADC g_tadc;
 extern unsigned long long g_nUpTime;
-extern void *g_pFwBuffer;
-extern size_t g_nCbFwData;
-extern struct mutex g_mutex;
+extern int g_backlight;
 
 extern struct kobj_attribute g_tivaVersionAtt;
 
@@ -32,12 +30,23 @@ extern struct kobj_attribute g_tivaTempTIVAAtt;
 extern struct bin_attribute g_tivaAdcBinAtt;
 
 extern struct kobj_attribute g_tivaUptimeAtt;
+extern struct kobj_attribute g_tivaBrightnessAtt;
+extern struct kobj_attribute g_tivaFrequencyAtt;
 
-extern struct bin_attribute g_tivaFirmwareAtt;
+extern struct bin_attribute g_tivaFwImageAtt;
+
+bool SfAttInit(void);
+void SfAttExit(void);
 
 void SfAttLockFirmware(bool bLock);
 bool SfAttIsFirmwareLocked(void);
 
+bool SfAttBacklightChanged(void);
+unsigned int SfAttGetBacklightBrightness(void);
+void SfAttSetBacklightBrightness(int val);
+unsigned int SfAttGetBacklightFrequency(void);
+void SfAttSetBacklightFrequency(int val);
+
 /////////////////////////////////////////////////////////////////////////////
 #ifdef __cplusplus
 }

+ 2 - 2
test/main.c

@@ -11,7 +11,7 @@
 #include <poll.h>
 #include <fcntl.h>
 #include <errno.h>
-#include "../defines.h"
+#include "../gfaspi.h"
 
 /////////////////////////////////////////////////////////////////////////////
 
@@ -170,7 +170,7 @@ int main(int argc, char *argv[])
 	{
 		int fd;
 		char szDevNode[128];
-		sprintf(szDevNode, "/sys/gfa/tiva/%s", attribs[i].pszName);
+        sprintf(szDevNode, "/sys/gfa/tiva/adc/%s", attribs[i].pszName);
 
 		if((fd = open(szDevNode, O_RDONLY, 0)) >= 0)
 		{