From caaadb4287017cda8eed8ea01c7c5bb3ba5f37b1 Mon Sep 17 00:00:00 2001 From: wesage <wesage@126.com> Date: Tue, 13 Aug 2013 21:48:28 +0800 Subject: [PATCH 12/40] Fix SATA_OK,201308132148,wesage --- .../device/softwinner/wing-k70/init.sun7i.rc | 1 + .../base/core/res/res/xml/storage_list.xml | 8 + android4.2/device/softwinner/wing-k70/vold.fstab | 1 + lichee/linux-3.3/.config | 34 +- .../arch/arm/mach-sun7i/include/mach/sys_config.h | 103 ++ lichee/linux-3.3/arch/arm/mach-sun7i/sys_config.c | 1708 +++++++++++++++++++- lichee/linux-3.3/drivers/ata/ahci.h | 6 + lichee/linux-3.3/drivers/ata/libahci.c | 13 +- lichee/linux-3.3/drivers/ata/sw_ahci_platform.c | 215 +-- lichee/linux-3.3/drivers/ata/sw_ahci_platform.h | 32 +- .../sun7i/configs/android/wing-k70/sys_config.fex | 2 +- 11 files changed, 1996 insertions(+), 127 deletions(-) diff --git a/android4.2/device/softwinner/wing-k70/init.sun7i.rc b/android4.2/device/softwinner/wing-k70/init.sun7i.rc index 8ebfdd6..012b656 100755 --- a/android4.2/device/softwinner/wing-k70/init.sun7i.rc +++ b/android4.2/device/softwinner/wing-k70/init.sun7i.rc @@ -9,6 +9,7 @@ on early-init mkdir /mnt/extsd 0000 system system mkdir /mnt/usbhost1 0000 system system mkdir /databk 0700 root system + mkdir /mnt/sata 0000 system system on early-fs mount ext4 /dev/block/system /system wait noatime nodev barrier=0 diff --git a/android4.2/device/softwinner/wing-k70/overlay/frameworks/base/core/res/res/xml/storage_list.xml b/android4.2/device/softwinner/wing-k70/overlay/frameworks/base/core/res/res/xml/storage_list.xml index 64e994b..5c19610 100755 --- a/android4.2/device/softwinner/wing-k70/overlay/frameworks/base/core/res/res/xml/storage_list.xml +++ b/android4.2/device/softwinner/wing-k70/overlay/frameworks/base/core/res/res/xml/storage_list.xml @@ -56,5 +56,13 @@ android:emulated="false" android:mtpReserve="0" android:maxFileSize="0"/> + <storage android:mountPoint="/mnt/sata" + android:storageDescription="sata" + android:primary="false" + android:removable="true" + android:emulated="false" + android:mtpReserve="0" + android:allowMassStorage="true" + android:maxFileSize="0"/> </StorageList> diff --git a/android4.2/device/softwinner/wing-k70/vold.fstab b/android4.2/device/softwinner/wing-k70/vold.fstab index 3034cea..9482dba 100755 --- a/android4.2/device/softwinner/wing-k70/vold.fstab +++ b/android4.2/device/softwinner/wing-k70/vold.fstab @@ -17,3 +17,4 @@ dev_mount sdcard /mnt/sdcard auto /devices/virtual/block/nandj /devices/platform/sunxi-mmc.2/mmc_host dev_mount extsd /mnt/extsd auto /devices/platform/sunxi-mmc.1/mmc_host /devices/platform/sunxi-mmc.0/mmc_host dev_mount usbhost1 /mnt/usbhost1 auto /devices/platform/sw-ehci.1 /devices/platform/sw_hcd_host0 /devices/platform/sw-ohci.1 +dev_mount sata /mnt/sata auto /devices/platform/sw_ahci.0/ata1/host0 diff --git a/lichee/linux-3.3/.config b/lichee/linux-3.3/.config index dbca6ed..663e61c 100644--- a/lichee/linux-3.3/.config +++ b/lichee/linux-3.3/.config @@ -970,7 +970,39 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_DH is not set # CONFIG_SCSI_OSD_INITIATOR is not set -# CONFIG_ATA is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_SW_SATA_AHCI_PLATFORM=y +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +# CONFIG_SATA_MV is not set + +# +# PATA SFF controllers with BMDMA +# + +# +# PIO-only SFF controllers +# + +# +# Generic fallback / legacy drivers +# CONFIG_MD=y # CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_DM=y diff --git a/lichee/linux-3.3/arch/arm/mach-sun7i/include/mach/sys_config.h b/lichee/linux-3.3/arch/arm/mach-sun7i/include/mach/sys_config.h index 1f50e9d..1dac71b 100644 --- a/lichee/linux-3.3/arch/arm/mach-sun7i/include/mach/sys_config.h +++ b/lichee/linux-3.3/arch/arm/mach-sun7i/include/mach/sys_config.h @@ -18,6 +18,36 @@ #include "gpio.h" +#define SYS_CONFIG_MEMBASE (PLAT_PHYS_OFFSET + SZ_32M + SZ_16M) +#define SYS_CONFIG_MEMSIZE (SZ_64K) +#define SCRIPT_PARSER_OK (0) +#define SCRIPT_PARSER_EMPTY_BUFFER (-1) +#define SCRIPT_PARSER_KEYNAME_NULL (-2) +#define SCRIPT_PARSER_DATA_VALUE_NULL (-3) +#define SCRIPT_PARSER_KEY_NOT_FIND (-4) +#define SCRIPT_PARSER_BUFFER_NOT_ENOUGH (-5) + +#define EGPIO_FAIL (-1) +#define EGPIO_SUCCESS (0) + + +/* + * define script sub key type, raw from sys_config.bin + * @SCIRPT_PARSER_VALUE_TYPE_INVALID: invalid type + * @SCIRPT_PARSER_VALUE_TYPE_SINGLE_WORD: int item type + * @SCIRPT_PARSER_VALUE_TYPE_STRING: string item type + * @SCIRPT_PARSER_VALUE_TYPE_MULTI_WORD: multi int type, not used currently + * @SCIRPT_PARSER_VALUE_TYPE_GPIO_WORD: gpio item type + */ +typedef enum { + SCIRPT_PARSER_VALUE_TYPE_INVALID = 0, + SCIRPT_PARSER_VALUE_TYPE_SINGLE_WORD, + SCIRPT_PARSER_VALUE_TYPE_STRING, + SCIRPT_PARSER_VALUE_TYPE_MULTI_WORD, + SCIRPT_PARSER_VALUE_TYPE_GPIO_WORD +} script_parser_value_type_t; + + /* * define types of script item * @SCIRPT_ITEM_VALUE_TYPE_INVALID: invalid item type @@ -45,6 +75,50 @@ typedef union { struct gpio_config gpio; } script_item_u; +typedef struct +{ + char gpio_name[32]; + int port; + int port_num; + int mul_sel; + int pull; + int drv_level; + int data; +} user_gpio_set_t; + + +typedef struct +{ + char gpio_name[32]; + int port; + int port_num; + int mul_sel; + int pull; + int drv_level; + int data; +} script_gpio_set_t; + +typedef struct +{ + int main_key_count; + int version[3]; +} script_head_t_ex; + +typedef struct +{ + char main_name[32]; + int lenth; + int offset; +} script_main_key_t_ex; + +typedef struct +{ + char sub_name[32]; + int offset; + int pattern; +} script_sub_key_t_ex; + + /* * script_get_item * get an item from script based on main_key & sub_key @@ -74,4 +148,33 @@ int script_get_pio_list(char *main_key, script_item_u **list); */ int script_dump_mainkey(char *main_key); + +/* script operations */ +extern int script_parser_init(char *script_buf); +extern int script_parser_exit(void); +extern int script_parser_fetch(char *main_name, char *sub_name, int value[], int count); +extern int script_parser_fetch_ex(char *main_name, char *sub_name, int value[], + script_parser_value_type_t *type, int count); +extern int script_parser_subkey_count(char *main_name); +extern int script_parser_mainkey_count(void); +extern int script_parser_mainkey_get_gpio_count(char *main_name); +extern int script_parser_mainkey_get_gpio_cfg(char *main_name, void *gpio_cfg, int gpio_count); + + + +/* gpio operations */ +extern int gpio_init(void); +extern int gpio_exit(void); +extern unsigned gpio_request_se(user_gpio_set_t *gpio_list, unsigned group_count_max); +extern unsigned gpio_request_ex(char *main_name, const char *sub_name); +extern int gpio_release(unsigned p_handler, int if_release_to_default_status); +extern int gpio_get_all_pin_status(unsigned p_handler, user_gpio_set_t *gpio_status, unsigned gpio_count_max, unsigned if_get_from_hardware); +extern int gpio_get_one_pin_status(unsigned p_handler, user_gpio_set_t *gpio_status, const char *gpio_name, unsigned if_get_from_hardware); +extern int gpio_set_one_pin_status(unsigned p_handler, user_gpio_set_t *gpio_status, const char *gpio_name, unsigned if_set_to_current_input_status); +extern int gpio_set_one_pin_io_status(unsigned p_handler, unsigned if_set_to_output_status, const char *gpio_name); +extern int gpio_set_one_pin_pull(unsigned p_handler, unsigned set_pull_status, const char *gpio_name); +extern int gpio_set_one_pin_driver_level(unsigned p_handler, unsigned set_driver_level, const char *gpio_name); +extern int gpio_read_one_pin_value(unsigned p_handler, const char *gpio_name); +extern int gpio_write_one_pin_value(unsigned p_handler, unsigned value_to_gpio, const char *gpio_name); + #endif diff --git a/lichee/linux-3.3/arch/arm/mach-sun7i/sys_config.c b/lichee/linux-3.3/arch/arm/mach-sun7i/sys_config.c index 88691a7..e716eb1 100644 --- a/lichee/linux-3.3/arch/arm/mach-sun7i/sys_config.c +++ b/lichee/linux-3.3/arch/arm/mach-sun7i/sys_config.c @@ -16,6 +16,7 @@ #include <linux/string.h> #include <linux/module.h> #include <linux/kernel.h> +#include <mach/platform.h> #include <mach/sys_config.h> #include <mach/gpio.h> #include <linux/slab.h> @@ -94,6 +95,10 @@ typedef struct { } script_origin_gpio_t; #pragma pack() + +u32 gpio_g_pioMemBase; + + /* *=========================================================================================================== * origin script defined as follows: @@ -207,21 +212,6 @@ typedef struct { void *next; } script_main_key_t; -/* - * define script sub key type, raw from sys_config.bin - * @SCIRPT_PARSER_VALUE_TYPE_INVALID: invalid type - * @SCIRPT_PARSER_VALUE_TYPE_SINGLE_WORD: int item type - * @SCIRPT_PARSER_VALUE_TYPE_STRING: string item type - * @SCIRPT_PARSER_VALUE_TYPE_MULTI_WORD: multi int type, not used currently - * @SCIRPT_PARSER_VALUE_TYPE_GPIO_WORD: gpio item type - */ -typedef enum { - SCIRPT_PARSER_VALUE_TYPE_INVALID = 0, - SCIRPT_PARSER_VALUE_TYPE_SINGLE_WORD, - SCIRPT_PARSER_VALUE_TYPE_STRING, - SCIRPT_PARSER_VALUE_TYPE_MULTI_WORD, - SCIRPT_PARSER_VALUE_TYPE_GPIO_WORD -} script_parser_value_type_t; static script_main_key_t *g_script; @@ -613,3 +603,1691 @@ static int script_debugfs_init(void) return 0; } core_initcall(script_debugfs_init); + + +/**######################################################################################## + * + * Script Operations + * +-#########################################################################################*/ +static char *script_mod_buf = NULL; //pointer to first key +static int script_main_key_count = 0; + + +static int _test_str_length(char *str) +{ + int length = 0; + + while(str[length++]) + { + if(length > 32) + { + length = 32; + break; + } + } + + return length; +} + +int script_parser_init(char *script_buf) +{ + script_head_t_ex *script_head; + + pr_debug("%s(%d)-%s, script_buf addr is %p:\n",__FILE__,__LINE__,__FUNCTION__, script_buf); + if(script_buf) + { + script_mod_buf = script_buf; + script_head = (script_head_t_ex *)script_mod_buf; + + script_main_key_count = script_head->main_key_count; + + pr_debug("succeed: %s(%d)-%s\n",__FILE__,__LINE__,__FUNCTION__); + return SCRIPT_PARSER_OK; + } + else + { + pr_warning("failed: %s(%d)-%s\n",__FILE__,__LINE__,__FUNCTION__); + return SCRIPT_PARSER_EMPTY_BUFFER; + } +} + +int script_parser_exit(void) +{ + script_mod_buf = NULL; + script_main_key_count = 0; + + return SCRIPT_PARSER_OK; +} + +int script_parser_fetch(char *main_name, char *sub_name, int value[], int count) +{ + char main_bkname[32], sub_bkname[32]; + char *main_char, *sub_char; + script_main_key_t_ex *main_key = NULL; + script_sub_key_t_ex *sub_key = NULL; + int i, j; + int pattern, word_count; + + pr_debug("enter script parse fetch. \n"); + + /* check params */ + if(!script_mod_buf) + { + return SCRIPT_PARSER_EMPTY_BUFFER; + } + + if((main_name == NULL) || (sub_name == NULL)) + { + return SCRIPT_PARSER_KEYNAME_NULL; + } + + if(value == NULL) + { + return SCRIPT_PARSER_DATA_VALUE_NULL; + } + + /* truncate string if size >31 bytes */ + main_char = main_name; + if(_test_str_length(main_name) > 31) + { + memset(main_bkname, 0, 32); + strncpy(main_bkname, main_name, 31); + main_char = main_bkname; + } + sub_char = sub_name; + if(_test_str_length(sub_name) > 31) + { + memset(sub_bkname, 0, 32); + strncpy(sub_bkname, sub_name, 31); + sub_char = sub_bkname; + } + pr_debug("gpio: main name is : %s, sub_name is: %s", main_char, sub_char); + + for(i=0;i<script_main_key_count;i++) + { + main_key = (script_main_key_t_ex *)(script_mod_buf + (sizeof(script_head_t_ex)) + i * sizeof(script_main_key_t_ex)); + if(strcmp(main_key->main_name, main_char)) + { + continue; + } + + /* now find sub key */ + for(j=0;j<main_key->lenth;j++) + { + sub_key = (script_sub_key_t_ex *)(script_mod_buf + (main_key->offset<<2) + (j * sizeof(script_sub_key_t_ex))); + if(strcmp(sub_key->sub_name, sub_char)) + { + continue; + } + pattern = (sub_key->pattern>>16) & 0xffff; /* get datatype */ + word_count = (sub_key->pattern>> 0) & 0xffff; /*get count of word */ + pr_debug("pattern is: 0x%x, word_count is: 0x%x, ", pattern, word_count); + + switch(pattern) + { + case SCIRPT_PARSER_VALUE_TYPE_SINGLE_WORD: + value[0] = *(int *)(script_mod_buf + (sub_key->offset<<2)); + break; + + case SCIRPT_PARSER_VALUE_TYPE_STRING: + if(count < word_count) + { + word_count = count; + } + memcpy((char *)value, script_mod_buf + (sub_key->offset<<2), word_count << 2); + break; + + case SCIRPT_PARSER_VALUE_TYPE_MULTI_WORD: + break; + case SCIRPT_PARSER_VALUE_TYPE_GPIO_WORD: + { + script_gpio_set_t *user_gpio_cfg = (script_gpio_set_t *)value; + /* buffer space enough? */ + if(sizeof(script_gpio_set_t) > (count<<2)) + { + return SCRIPT_PARSER_BUFFER_NOT_ENOUGH; + } + strcpy( user_gpio_cfg->gpio_name, sub_char); + memcpy(&user_gpio_cfg->port, script_mod_buf + (sub_key->offset<<2), sizeof(script_gpio_set_t) - 32); + break; + } + } + + return SCRIPT_PARSER_OK; + } + } + + return SCRIPT_PARSER_KEY_NOT_FIND; +} +EXPORT_SYMBOL(script_parser_fetch); + +int script_parser_fetch_ex(char *main_name, char *sub_name, int value[], script_parser_value_type_t *type, int count) +{ + char main_bkname[32], sub_bkname[32]; + char *main_char, *sub_char; + script_main_key_t_ex *main_key = NULL; + script_sub_key_t_ex *sub_key = NULL; + int i, j; + int pattern, word_count; + script_parser_value_type_t *value_type = type; + + pr_debug("enter script parse fetch. \n"); + + if(!script_mod_buf) + { + return SCRIPT_PARSER_EMPTY_BUFFER; + } + + if((main_name == NULL) || (sub_name == NULL)) + { + return SCRIPT_PARSER_KEYNAME_NULL; + } + + if(value == NULL) + { + return SCRIPT_PARSER_DATA_VALUE_NULL; + } + + main_char = main_name; + if(_test_str_length(main_name) > 31) + { + memset(main_bkname, 0, 32); + strncpy(main_bkname, main_name, 31); + main_char = main_bkname; + } + sub_char = sub_name; + if(_test_str_length(sub_name) > 31) + { + memset(sub_bkname, 0, 32); + strncpy(sub_bkname, sub_name, 31); + sub_char = sub_bkname; + } + pr_debug("gpio: main name is : %s, sub_name is: %s", main_char, sub_char); + + for(i=0;i<script_main_key_count;i++) + { + main_key = (script_main_key_t_ex *)(script_mod_buf + (sizeof(script_head_t_ex)) + i * sizeof(script_main_key_t_ex)); + if(strcmp(main_key->main_name, main_char)) + { + continue; + } + + for(j=0;j<main_key->lenth;j++) + { + sub_key = (script_sub_key_t_ex *)(script_mod_buf + (main_key->offset<<2) + (j * sizeof(script_sub_key_t_ex))); + if(strcmp(sub_key->sub_name, sub_char)) + { + continue; + } + pattern = (sub_key->pattern>>16) & 0xffff; + word_count = (sub_key->pattern>> 0) & 0xffff; + pr_debug("pattern is: 0x%x, word_count is: 0x%x, ", pattern, word_count); + + switch(pattern) + { + case SCIRPT_PARSER_VALUE_TYPE_SINGLE_WORD: + value[0] = *(int *)(script_mod_buf + (sub_key->offset<<2)); + *value_type = SCIRPT_PARSER_VALUE_TYPE_SINGLE_WORD; + break; + + case SCIRPT_PARSER_VALUE_TYPE_STRING: + if(count < word_count) + { + word_count = count; + } + memcpy((char *)value, script_mod_buf + (sub_key->offset<<2), word_count << 2); + *value_type = SCIRPT_PARSER_VALUE_TYPE_STRING; + break; + + case SCIRPT_PARSER_VALUE_TYPE_MULTI_WORD: + *value_type = SCIRPT_PARSER_VALUE_TYPE_MULTI_WORD; + break; + case SCIRPT_PARSER_VALUE_TYPE_GPIO_WORD: + { + script_gpio_set_t *user_gpio_cfg = (script_gpio_set_t *)value; + + if(sizeof(script_gpio_set_t) > (count<<2)) + { + return SCRIPT_PARSER_BUFFER_NOT_ENOUGH; + } + strcpy( user_gpio_cfg->gpio_name, sub_char); + memcpy(&user_gpio_cfg->port, script_mod_buf + (sub_key->offset<<2), sizeof(script_gpio_set_t) - 32); + *value_type = SCIRPT_PARSER_VALUE_TYPE_GPIO_WORD; + break; + } + } + + return SCRIPT_PARSER_OK; + } + } + + return SCRIPT_PARSER_KEY_NOT_FIND; +} +EXPORT_SYMBOL(script_parser_fetch_ex); + +int script_parser_subkey_count(char *main_name) +{ + char main_bkname[32]; + char *main_char; + script_main_key_t_ex *main_key = NULL; + int i; + + if(!script_mod_buf) + { + return SCRIPT_PARSER_EMPTY_BUFFER; + } + + if(main_name == NULL) + { + return SCRIPT_PARSER_KEYNAME_NULL; + } + + main_char = main_name; + if(_test_str_length(main_name) > 31) + { + memset(main_bkname, 0, 32); + strncpy(main_bkname, main_name, 31); + main_char = main_bkname; + } + + for(i=0;i<script_main_key_count;i++) + { + main_key = (script_main_key_t_ex *)(script_mod_buf + (sizeof(script_head_t_ex)) + i * sizeof(script_main_key_t_ex)); + if(strcmp(main_key->main_name, main_char)) + { + continue; + } + + return main_key->lenth; + } + + return -1; +} + +int script_parser_mainkey_count(void) +{ + if(!script_mod_buf) + { + return SCRIPT_PARSER_EMPTY_BUFFER; + } + + return script_main_key_count; +} + +int script_parser_mainkey_get_gpio_count(char *main_name) +{ + char main_bkname[32]; + char *main_char; + script_main_key_t_ex *main_key = NULL; + script_sub_key_t_ex *sub_key = NULL; + int i, j; + int pattern, gpio_count = 0; + + if(!script_mod_buf) + { + return SCRIPT_PARSER_EMPTY_BUFFER; + } + + if(main_name == NULL) + { + return SCRIPT_PARSER_KEYNAME_NULL; + } + + main_char = main_name; + if(_test_str_length(main_name) > 31) + { + memset(main_bkname, 0, 32); + strncpy(main_bkname, main_name, 31); + main_char = main_bkname; + } + + for(i=0;i<script_main_key_count;i++) + { + main_key = (script_main_key_t_ex *)(script_mod_buf + (sizeof(script_head_t_ex)) + i * sizeof(script_main_key_t_ex)); + if(strcmp(main_key->main_name, main_char)) + { + continue; + } + + for(j=0;j<main_key->lenth;j++) + { + sub_key = (script_sub_key_t_ex *)(script_mod_buf + (main_key->offset<<2) + (j * sizeof(script_sub_key_t_ex))); + + pattern = (sub_key->pattern>>16) & 0xffff; + + if(SCIRPT_PARSER_VALUE_TYPE_GPIO_WORD == pattern) + { + gpio_count ++; + } + } + } + + return gpio_count; +} +EXPORT_SYMBOL(script_parser_mainkey_get_gpio_count); + +int script_parser_mainkey_get_gpio_cfg(char *main_name, void *gpio_cfg, int gpio_count) +{ + char main_bkname[32]; + char *main_char; + script_main_key_t_ex *main_key = NULL; + script_sub_key_t_ex *sub_key = NULL; + script_gpio_set_t *user_gpio_cfg = (script_gpio_set_t *)gpio_cfg; + int i, j; + int pattern, user_index; + + if(!script_mod_buf) + { + return SCRIPT_PARSER_EMPTY_BUFFER; + } + + if(main_name == NULL) + { + return SCRIPT_PARSER_KEYNAME_NULL; + } + + memset(user_gpio_cfg, 0, sizeof(script_gpio_set_t) * gpio_count); + + main_char = main_name; + if(_test_str_length(main_name) > 31) + { + memset(main_bkname, 0, 32); + strncpy(main_bkname, main_name, 31); + main_char = main_bkname; + } + + for(i=0;i<script_main_key_count;i++) + { + main_key = (script_main_key_t_ex *)(script_mod_buf + (sizeof(script_head_t_ex)) + i * sizeof(script_main_key_t_ex)); + if(strcmp(main_key->main_name, main_char)) + { + continue; + } + + pr_debug("mainkey name = %s\n", main_key->main_name); + user_index = 0; + for(j=0;j<main_key->lenth;j++) + { + sub_key = (script_sub_key_t_ex *)(script_mod_buf + (main_key->offset<<2) + (j * sizeof(script_sub_key_t_ex))); + pr_debug("subkey name = %s\n", sub_key->sub_name); + pattern = (sub_key->pattern>>16) & 0xffff; + pr_debug("subkey pattern = %d\n", pattern); + + if(SCIRPT_PARSER_VALUE_TYPE_GPIO_WORD == pattern) + { + strcpy( user_gpio_cfg[user_index].gpio_name, sub_key->sub_name); + memcpy(&user_gpio_cfg[user_index].port, script_mod_buf + (sub_key->offset<<2), sizeof(script_gpio_set_t) - 32); + user_index++; + if(user_index >= gpio_count) + { + break; + } + } + } + return SCRIPT_PARSER_OK; + } + + return SCRIPT_PARSER_KEY_NOT_FIND; +} + + + +/**############################################################################################################# + * + * GPIO(PIN) Operations + * +-##############################################################################################################*/ +#define CSP_OSAL_PHY_2_VIRT(phys, size) SW_VA_PORTC_IO_BASE +#define CSP_OSAL_MALLOC(size) kmalloc((size), GFP_ATOMIC) +#define CSP_OSAL_FREE(ptr) kfree((ptr)) + +#define CSP_PIN_PHY_ADDR_BASE SW_PA_PORTC_IO_BASE +#define CSP_PIN_PHY_ADDR_SIZE 0x1000 + + u32 gpio_g_pioMemBase = 0; +#define PIOC_REGS_BASE gpio_g_pioMemBase + + extern char sys_cofig_data[]; + extern char sys_cofig_data_end[]; +#define __REG(x) (*(volatile unsigned int *)(x)) + +#define PIO_REG_CFG(n, i) ((volatile unsigned int *)( PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x00)) +#define PIO_REG_DLEVEL(n, i) ((volatile unsigned int *)( PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x14)) +#define PIO_REG_PULL(n, i) ((volatile unsigned int *)( PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x1C)) +#define PIO_REG_DATA(n) ((volatile unsigned int *)( PIOC_REGS_BASE + ((n)-1)*0x24 + 0x10)) + +#define PIO_REG_CFG_VALUE(n, i) __REG( PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x00) +#define PIO_REG_DLEVEL_VALUE(n, i) __REG( PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x14) +#define PIO_REG_PULL_VALUE(n, i) __REG( PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x1C) +#define PIO_REG_DATA_VALUE(n) __REG( PIOC_REGS_BASE + ((n)-1)*0x24 + 0x10) + + +typedef struct +{ + int mul_sel; + int pull; + int drv_level; + int data; +} gpio_status_set_t; + +typedef struct +{ + char gpio_name[32]; + int port; + int port_num; + gpio_status_set_t user_gpio_status; + gpio_status_set_t hardware_gpio_status; +} system_gpio_set_t; + + +/* +**************************************************************************************************** +* +* CSP_PIN_init +* +* Description: +* init +* +* Parameters: +* Return value: +* EGPIO_SUCCESS/EGPIO_FAIL +**************************************************************************************************** +*/ +int gpio_init(void) +{ + printk("Init eGon pin module V2.0\n"); + gpio_g_pioMemBase = (u32)CSP_OSAL_PHY_2_VIRT(CSP_PIN_PHY_ADDR_BASE , CSP_PIN_PHY_ADDR_SIZE); + #ifdef FPGA_RUNTIME_ENV + return script_parser_init((char *)(sys_cofig_data)); + #else + return script_parser_init((char *)__va(SYS_CONFIG_MEMBASE)); + #endif +} +fs_initcall(gpio_init); + +/* +**************************************************************************************************** +* +* CSP_PIN_exit +* +* Description: +* exit +* +* Parameters: +* +* Return value: +* EGPIO_SUCCESS/EGPIO_FAIL +**************************************************************************************************** +*/ +__s32 gpio_exit(void) +{ + return 0; +} + +/* +************************************************************************************************************ +* +* CSP_GPIO_Request +* +* 函数名称: +* +* 参数列表:gpio_list 存放所有用到的GPIO数据的数组,GPIO将直接使用这个数组 +* +* group_count_max 数组的成员个数,GPIO设定的时候,将操作的GPIO最大不超过这个值 +* +* 返回值 : +* +* 说明 :暂时没有做冲突检查 +* +* +************************************************************************************************************ +*/ +u32 gpio_request_se(user_gpio_set_t *gpio_list, __u32 group_count_max) +{ + char *user_gpio_buf; //按照char类型申请 + system_gpio_set_t *user_gpio_set, *tmp_sys_gpio_data; //user_gpio_set将是申请内存的句柄 + user_gpio_set_t *tmp_user_gpio_data; + __u32 real_gpio_count = 0, first_port; //保存真正有效的GPIO的个数 + __u32 tmp_group_func_data = 0; + __u32 tmp_group_pull_data = 0; + __u32 tmp_group_dlevel_data = 0; + __u32 tmp_group_data_data = 0; + __u32 func_change = 0, pull_change = 0; + __u32 dlevel_change = 0, data_change = 0; + volatile __u32 *tmp_group_func_addr = NULL, *tmp_group_pull_addr = NULL; + volatile __u32 *tmp_group_dlevel_addr = NULL, *tmp_group_data_addr = NULL; + __u32 port, port_num, port_num_func, port_num_pull; + __u32 pre_port = 0x7fffffff, pre_port_num_func = 0x7fffffff; + __u32 pre_port_num_pull = 0x7fffffff; + __s32 i, tmp_val; + + if((!gpio_list) || (!group_count_max)) + { + return (u32)0; + } + for(i = 0; i < group_count_max; i++) + { + tmp_user_gpio_data = gpio_list + i; //gpio_set依次指向每个GPIO数组成员 + if(!tmp_user_gpio_data->port) + { + continue; + } + real_gpio_count ++; + } + + //printk("to malloc space for pin \n"); + user_gpio_buf = (char *)CSP_OSAL_MALLOC(16 + sizeof(system_gpio_set_t) * real_gpio_count); //申请内存,多申请16个字节,用于存放GPIO个数等信息 + if(!user_gpio_buf) + { + return (u32)0; + } + memset(user_gpio_buf, 0, 16 + sizeof(system_gpio_set_t) * real_gpio_count); //首先全部清零 + *(int *)user_gpio_buf = real_gpio_count; //保存有效的GPIO个数 + user_gpio_set = (system_gpio_set_t *)(user_gpio_buf + 16); //指向第一个结构体 + //准备第一个GPIO数据 + for(first_port = 0; first_port < group_count_max; first_port++) + { + tmp_user_gpio_data = gpio_list + first_port; + port = tmp_user_gpio_data->port; //读出端口数值 + port_num = tmp_user_gpio_data->port_num; //读出端口中的某一个GPIO + if(!port) + { + continue; + } + port_num_func = (port_num >> 3); + port_num_pull = (port_num >> 4); + + tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址 + tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); //更新pull寄存器 + tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_pull);//更新level寄存器 + tmp_group_data_addr = PIO_REG_DATA(port); //更新data寄存器 + + tmp_group_func_data = *tmp_group_func_addr; + tmp_group_pull_data = *tmp_group_pull_addr; + tmp_group_dlevel_data = *tmp_group_dlevel_addr; + tmp_group_data_data = *tmp_group_data_addr; + break; + } + if(first_port >= group_count_max) + { + return 0; + } + //保存用户数据 + for(i = first_port; i < group_count_max; i++) + { + tmp_sys_gpio_data = user_gpio_set + i; //tmp_sys_gpio_data指向申请的GPIO空间 + tmp_user_gpio_data = gpio_list + i; //gpio_set依次指向用户的每个GPIO数组成员 + port = tmp_user_gpio_data->port; //读出端口数值 + port_num = tmp_user_gpio_data->port_num; //读出端口中的某一个GPIO + if(!port) + { + continue; + } + //开始保存用户数据 + strcpy(tmp_sys_gpio_data->gpio_name, tmp_user_gpio_data->gpio_name); + tmp_sys_gpio_data->port = port; + tmp_sys_gpio_data->port_num = port_num; + tmp_sys_gpio_data->user_gpio_status.mul_sel = tmp_user_gpio_data->mul_sel; + tmp_sys_gpio_data->user_gpio_status.pull = tmp_user_gpio_data->pull; + tmp_sys_gpio_data->user_gpio_status.drv_level = tmp_user_gpio_data->drv_level; + tmp_sys_gpio_data->user_gpio_status.data = tmp_user_gpio_data->data; + + port_num_func = (port_num >> 3); + port_num_pull = (port_num >> 4); + + if((port_num_pull != pre_port_num_pull) || (port != pre_port)) //如果发现当前引脚的端口不一致,或者所在的pull寄存器不一致 + { + if(func_change) + { + *tmp_group_func_addr = tmp_group_func_data; //回写功能寄存器 + func_change = 0; + } + if(pull_change) + { + pull_change = 0; + *tmp_group_pull_addr = tmp_group_pull_data; //回写pull寄存器 + } + if(dlevel_change) + { + dlevel_change = 0; + *tmp_group_dlevel_addr = tmp_group_dlevel_data; //回写driver level寄存器 + } + if(data_change) + { + data_change = 0; + *tmp_group_data_addr = tmp_group_data_data; //回写 + } + + tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址 + tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); //更新pull寄存器 + tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_pull); //更新level寄存器 + tmp_group_data_addr = PIO_REG_DATA(port); //更新data寄存器 + + tmp_group_func_data = *tmp_group_func_addr; + tmp_group_pull_data = *tmp_group_pull_addr; + tmp_group_dlevel_data = *tmp_group_dlevel_addr; + tmp_group_data_data = *tmp_group_data_addr; + + } + else if(pre_port_num_func != port_num_func) //如果发现当前引脚的功能寄存器不一致 + { + *tmp_group_func_addr = tmp_group_func_data; //则只回写功能寄存器 + tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址 + + tmp_group_func_data = *tmp_group_func_addr; + } + //保存当前硬件寄存器数据 + pre_port_num_pull = port_num_pull; //设置当前GPIO成为前一个GPIO + pre_port_num_func = port_num_func; + pre_port = port; + + //更新功能寄存器 + if(tmp_user_gpio_data->mul_sel >= 0) + { + tmp_val = (port_num - (port_num_func<<3)) << 2; + tmp_sys_gpio_data->hardware_gpio_status.mul_sel = (tmp_group_func_data >> tmp_val) & 0x07; + tmp_group_func_data &= ~( 0x07 << tmp_val); + tmp_group_func_data |= (tmp_user_gpio_data->mul_sel & 0x07) << tmp_val; + func_change = 1; + } + //根据pull的值决定是否更新pull寄存器 + + tmp_val = (port_num - (port_num_pull<<4)) << 1; + + if(tmp_user_gpio_data->pull >= 0) + { + tmp_sys_gpio_data->hardware_gpio_status.pull = (tmp_group_pull_data >> tmp_val) & 0x03; + if(tmp_user_gpio_data->pull >= 0) + { + tmp_group_pull_data &= ~( 0x03 << tmp_val); + tmp_group_pull_data |= (tmp_user_gpio_data->pull & 0x03) << tmp_val; + pull_change = 1; + } + } + //根据driver level的值决定是否更新driver level寄存器 + if(tmp_user_gpio_data->drv_level >= 0) + { + tmp_sys_gpio_data->hardware_gpio_status.drv_level = (tmp_group_dlevel_data >> tmp_val) & 0x03; + if(tmp_user_gpio_data->drv_level >= 0) + { + tmp_group_dlevel_data &= ~( 0x03 << tmp_val); + tmp_group_dlevel_data |= (tmp_user_gpio_data->drv_level & 0x03) << tmp_val; + dlevel_change = 1; + } + } + //根据用户输入,以及功能分配决定是否更新data寄存器 + if(tmp_user_gpio_data->mul_sel == 1) + { + if(tmp_user_gpio_data->data >= 0) + { + tmp_val = tmp_user_gpio_data->data; + tmp_val &= 1; + tmp_group_data_data &= ~(1 << port_num); + tmp_group_data_data |= tmp_val << port_num; + data_change = 1; + } + } + } + //for循环结束,如果存在还没有回写的寄存器,这里写回到硬件当中 + if(tmp_group_func_addr) //只要更新过寄存器地址,就可以对硬件赋值 + { //那么把所有的值全部回写到硬件寄存器 + *tmp_group_func_addr = tmp_group_func_data; //回写功能寄存器 + if(pull_change) + { + *tmp_group_pull_addr = tmp_group_pull_data; //回写pull寄存器 + } + if(dlevel_change) + { + *tmp_group_dlevel_addr = tmp_group_dlevel_data; //回写driver level寄存器 + } + if(data_change) + { + *tmp_group_data_addr = tmp_group_data_data; //回写data寄存器 + } + } + + return (u32)user_gpio_buf; +} +EXPORT_SYMBOL_GPL(gpio_request_se); + +/* +************************************************************************************************************ +* +* CSP_GPIO_Request_EX +* +* 函数名称: +* +* 参数说明: main_name 传进的主键名称,匹配模块(驱动名称) +* +* sub_name 传进的子键名称,如果是空,表示全部,否则寻找到匹配的单独GPIO +* +* 返回值 :0 : err +* other: success +* +* 说明 :暂时没有做冲突检查 +* +* +************************************************************************************************************ +*/ +u32 gpio_request_ex(char *main_name, const char *sub_name) //设备申请GPIO函数扩展接口 +{ + user_gpio_set_t *gpio_list=NULL; + user_gpio_set_t one_gpio; + __u32 gpio_handle; + __s32 gpio_count; + + if(!sub_name){ + gpio_count = script_parser_mainkey_get_gpio_count(main_name); + if(gpio_count <= 0) + { + printk("err: gpio count < =0 ,gpio_count is: %d \n", gpio_count); + return 0; + } + gpio_list = (user_gpio_set_t *)CSP_OSAL_MALLOC(sizeof(system_gpio_set_t) * gpio_count); //申请一片临时内存,用于保存用户数据 + if(!gpio_list){ + printk("malloc gpio_list error \n"); + return 0; + } + if(!script_parser_mainkey_get_gpio_cfg(main_name,gpio_list,gpio_count)){ + gpio_handle = gpio_request_se(gpio_list, gpio_count); + CSP_OSAL_FREE(gpio_list); + + }else{ + return 0; + } + }else{ + if(script_parser_fetch((char *)main_name, (char *)sub_name, (int *)&one_gpio, (sizeof(user_gpio_set_t) >> 2)) < 0){ + printk("script parser fetch err. \n"); + return 0; + } + + gpio_handle = gpio_request_se(&one_gpio, 1); + } + + return gpio_handle; +} +EXPORT_SYMBOL(gpio_request_ex); + +/* +**************************************************************************************************** +* +* CSP_PIN_DEV_release +* +* Description: +* 释放某逻辑设备的pin +* +* Parameters: +* p_handler : handler +* if_release_to_default_status : 是否释放到原始状态(寄存器原有状态) +* +* Return value: +* EGPIO_SUCCESS/EGPIO_FAIL +**************************************************************************************************** +*/ +__s32 gpio_release(u32 p_handler, __s32 if_release_to_default_status) +{ + char *tmp_buf; //转换成char类型 + __u32 group_count_max, first_port; //最大GPIO个数 + system_gpio_set_t *user_gpio_set, *tmp_sys_gpio_data; + __u32 tmp_group_func_data = 0; + __u32 tmp_group_pull_data = 0; + __u32 tmp_group_dlevel_data = 0; + volatile __u32 *tmp_group_func_addr = NULL, *tmp_group_pull_addr = NULL; + volatile __u32 *tmp_group_dlevel_addr = NULL; + __u32 port, port_num, port_num_pull, port_num_func; + __u32 pre_port = 0x7fffffff, pre_port_num_func = 0x7fffffff, pre_port_num_pull = 0x7fffffff; + __u32 i, tmp_val; + + //检查传进的句柄的有效性 + if(!p_handler) + { + return EGPIO_FAIL; + } + tmp_buf = (char *)p_handler; + group_count_max = *(int *)tmp_buf; + if(!group_count_max) + { + return EGPIO_FAIL; + } + if(if_release_to_default_status == 2) + { + //printk("gpio module : release p_handler = %x\n",p_handler); + CSP_OSAL_FREE((char *)p_handler); + + return EGPIO_SUCCESS; + } + user_gpio_set = (system_gpio_set_t *)(tmp_buf + 16); + //读取用户数据 + for(first_port = 0; first_port < group_count_max; first_port++) + { + tmp_sys_gpio_data = user_gpio_set + first_port; + port = tmp_sys_gpio_data->port; //读出端口数值 + port_num = tmp_sys_gpio_data->port_num; //读出端口中的某一个GPIO + if(!port) + { + continue; + } + port_num_func = (port_num >> 3); + port_num_pull = (port_num >> 4); + + tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址 + tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); //更新pull寄存器 + tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_pull);//更新level寄存器 + + tmp_group_func_data = *tmp_group_func_addr; + tmp_group_pull_data = *tmp_group_pull_addr; + tmp_group_dlevel_data = *tmp_group_dlevel_addr; + break; + } + if(first_port >= group_count_max) + { + return 0; + } + for(i = first_port; i < group_count_max; i++) + { + tmp_sys_gpio_data = user_gpio_set + i; //tmp_sys_gpio_data指向申请的GPIO空间 + port = tmp_sys_gpio_data->port; //读出端口数值 + port_num = tmp_sys_gpio_data->port_num; //读出端口中的某一个GPIO + + port_num_func = (port_num >> 3); + port_num_pull = (port_num >> 4); + + if((port_num_pull != pre_port_num_pull) || (port != pre_port)) //如果发现当前引脚的端口不一致,或者所在的pull寄存器不一致 + { + *tmp_group_func_addr = tmp_group_func_data; //回写功能寄存器 + *tmp_group_pull_addr = tmp_group_pull_data; //回写pull寄存器 + *tmp_group_dlevel_addr = tmp_group_dlevel_data; //回写driver level寄存器 + + tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址 + tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); //更新pull寄存器 + tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_pull); //更新level寄存器 + + tmp_group_func_data = *tmp_group_func_addr; + tmp_group_pull_data = *tmp_group_pull_addr; + tmp_group_dlevel_data = *tmp_group_dlevel_addr; + } + else if(pre_port_num_func != port_num_func) //如果发现当前引脚的功能寄存器不一致 + { + *tmp_group_func_addr = tmp_group_func_data; //则只回写功能寄存器 + tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址 + tmp_group_func_data = *tmp_group_func_addr; + } + + pre_port_num_pull = port_num_pull; + pre_port_num_func = port_num_func; + pre_port = port; + //更新功能寄存器 + tmp_group_func_data &= ~(0x07 << ((port_num - (port_num_func<<3)) << 2)); + //更新pull状态寄存器 + tmp_val = (port_num - (port_num_pull<<4)) << 1; + tmp_group_pull_data &= ~(0x03 << tmp_val); + tmp_group_pull_data |= (tmp_sys_gpio_data->hardware_gpio_status.pull & 0x03) << tmp_val; + //更新driver状态寄存器 + tmp_val = (port_num - (port_num_pull<<4)) << 1; + tmp_group_dlevel_data &= ~(0x03 << tmp_val); + tmp_group_dlevel_data |= (tmp_sys_gpio_data->hardware_gpio_status.drv_level & 0x03) << tmp_val; + } + if(tmp_group_func_addr) //只要更新过寄存器地址,就可以对硬件赋值 + { //那么把所有的值全部回写到硬件寄存器 + *tmp_group_func_addr = tmp_group_func_data; //回写功能寄存器 + } + if(tmp_group_pull_addr) + { + *tmp_group_pull_addr = tmp_group_pull_data; + } + if(tmp_group_dlevel_addr) + { + *tmp_group_dlevel_addr = tmp_group_dlevel_data; + } + + CSP_OSAL_FREE((char *)p_handler); + + return EGPIO_SUCCESS; +} +EXPORT_SYMBOL(gpio_release); + +/* +********************************************************************************************************************** +* CSP_PIN_Get_All_Gpio_Status +* +* Description: +* 获取用户申请过的所有GPIO的状态 +* Arguments : +* p_handler : handler +* gpio_status : 保存用户数据的数组 +* gpio_count_max : 数组最大个数,避免数组越界 +* if_get_user_set_flag : 读取标志,表示读取用户设定数据或者是实际数据 +* Returns : +* +* Notes : +* +********************************************************************************************************************** +*/ +__s32 gpio_get_all_pin_status(u32 p_handler, user_gpio_set_t *gpio_status, __u32 gpio_count_max, __u32 if_get_from_hardware) +{ + char *tmp_buf; //转换成char类型 + __u32 group_count_max, first_port; //最大GPIO个数 + system_gpio_set_t *user_gpio_set, *tmp_sys_gpio_data; + user_gpio_set_t *script_gpio; + __u32 port_num_func, port_num_pull; + volatile __u32 *tmp_group_func_addr = NULL, *tmp_group_pull_addr; + volatile __u32 *tmp_group_data_addr, *tmp_group_dlevel_addr; + __u32 port, port_num; + __u32 pre_port = 0x7fffffff, pre_port_num_func = 0x7fffffff, pre_port_num_pull = 0x7fffffff; + __u32 i; + + if((!p_handler) || (!gpio_status)) + { + return EGPIO_FAIL; + } + if(gpio_count_max <= 0) + { + return EGPIO_FAIL; + } + tmp_buf = (char *)p_handler; + group_count_max = *(int *)tmp_buf; + if(group_count_max <= 0) + { + return EGPIO_FAIL; + } + user_gpio_set = (system_gpio_set_t *)(tmp_buf + 16); + if(group_count_max > gpio_count_max) + { + group_count_max = gpio_count_max; + } + //读取用户数据 + //表示读取用户给定的数据 + if(!if_get_from_hardware) + { + for(i = 0; i < group_count_max; i++) + { + tmp_sys_gpio_data = user_gpio_set + i; //tmp_sys_gpio_data指向申请的GPIO空间 + script_gpio = gpio_status + i; //script_gpio指向用户传进的空间 + + script_gpio->port = tmp_sys_gpio_data->port; //读出port数据 + script_gpio->port_num = tmp_sys_gpio_data->port_num; //读出port_num数据 + script_gpio->pull = tmp_sys_gpio_data->user_gpio_status.pull; //读出pull数据 + script_gpio->mul_sel = tmp_sys_gpio_data->user_gpio_status.mul_sel; //读出功能数据 + script_gpio->drv_level = tmp_sys_gpio_data->user_gpio_status.drv_level; //读出驱动能力数据 + script_gpio->data = tmp_sys_gpio_data->user_gpio_status.data; //读出data数据 + strcpy(script_gpio->gpio_name, tmp_sys_gpio_data->gpio_name); + } + } + else + { + for(first_port = 0; first_port < group_count_max; first_port++) + { + tmp_sys_gpio_data = user_gpio_set + first_port; + port = tmp_sys_gpio_data->port; //读出端口数值 + port_num = tmp_sys_gpio_data->port_num; //读出端口中的某一个GPIO + + if(!port) + { + continue; + } + port_num_func = (port_num >> 3); + port_num_pull = (port_num >> 4); + tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址 + tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); //更新pull寄存器 + tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_pull); //更新level寄存器 + tmp_group_data_addr = PIO_REG_DATA(port); //更新data寄存器 + break; + } + if(first_port >= group_count_max) + { + return 0; + } + for(i = first_port; i < group_count_max; i++) + { + tmp_sys_gpio_data = user_gpio_set + i; //tmp_sys_gpio_data指向申请的GPIO空间 + script_gpio = gpio_status + i; //script_gpio指向用户传进的空间 + + port = tmp_sys_gpio_data->port; //读出端口数值 + port_num = tmp_sys_gpio_data->port_num; //读出端口中的某一个GPIO + + script_gpio->port = port; //读出port数据 + script_gpio->port_num = port_num; //读出port_num数据 + strcpy(script_gpio->gpio_name, tmp_sys_gpio_data->gpio_name); + + port_num_func = (port_num >> 3); + port_num_pull = (port_num >> 4); + + if((port_num_pull != pre_port_num_pull) || (port != pre_port)) //如果发现当前引脚的端口不一致,或者所在的pull寄存器不一致 + { + tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址 + tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); //更新pull寄存器 + tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_pull); //更新level寄存器 + tmp_group_data_addr = PIO_REG_DATA(port); //更新data寄存器 + } + else if(pre_port_num_func != port_num_func) //如果发现当前引脚的功能寄存器不一致 + { + tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址 + } + + pre_port_num_pull = port_num_pull; + pre_port_num_func = port_num_func; + pre_port = port; + //给用户控件赋值 + script_gpio->pull = (*tmp_group_pull_addr >> ((port_num - (port_num_pull<<4))<<1)) & 0x03; //读出pull数据 + script_gpio->drv_level = (*tmp_group_dlevel_addr >> ((port_num - (port_num_pull<<4))<<1)) & 0x03; //读出功能数据 + script_gpio->mul_sel = (*tmp_group_func_addr >> ((port_num - (port_num_func<<3))<<2)) & 0x07; //读出功能数据 + if(script_gpio->mul_sel <= 1) + { + script_gpio->data = (*tmp_group_data_addr >> port_num) & 0x01; //读出data数据 + } + else + { + script_gpio->data = -1; + } + } + } + + return EGPIO_SUCCESS; +} +EXPORT_SYMBOL(gpio_get_all_pin_status); + +/* +********************************************************************************************************************** +* CSP_GPIO_Get_One_PIN_Status +* +* Description: +* 获取用户申请过的所有GPIO的状态 +* Arguments : +* p_handler : handler +* gpio_status : 保存用户数据的数组 +* gpio_name : 要操作的GPIO的名称 +* if_get_user_set_flag : 读取标志,表示读取用户设定数据或者是实际数据 +* Returns : +* +* Notes : +* +********************************************************************************************************************** +*/ +__s32 gpio_get_one_pin_status(u32 p_handler, user_gpio_set_t *gpio_status, const char *gpio_name, __u32 if_get_from_hardware) +{ + char *tmp_buf; //转换成char类型 + __u32 group_count_max; //最大GPIO个数 + system_gpio_set_t *user_gpio_set, *tmp_sys_gpio_data; + __u32 port_num_func, port_num_pull; + __u32 port, port_num; + __u32 i, tmp_val1, tmp_val2; + + //检查传进的句柄的有效性 + if((!p_handler) || (!gpio_status)) + { + return EGPIO_FAIL; + } + tmp_buf = (char *)p_handler; + group_count_max = *(int *)tmp_buf; + if(group_count_max <= 0) + { + return EGPIO_FAIL; + } + else if((group_count_max > 1) && (!gpio_name)) + { + return EGPIO_FAIL; + } + user_gpio_set = (system_gpio_set_t *)(tmp_buf + 16); + //读取用户数据 + //表示读取用户给定的数据 + for(i = 0; i < group_count_max; i++) + { + tmp_sys_gpio_data = user_gpio_set + i; //tmp_sys_gpio_data指向申请的GPIO空间 + if(strcmp(gpio_name, tmp_sys_gpio_data->gpio_name)) + { + continue; + } + strcpy(gpio_status->gpio_name, tmp_sys_gpio_data->gpio_name); + port = tmp_sys_gpio_data->port; + port_num = tmp_sys_gpio_data->port_num; + gpio_status->port = port; //读出port数据 + gpio_status->port_num = port_num; //读出port_num数据 + + if(!if_get_from_hardware) //当前要求读出用户设计的数据 + { + gpio_status->mul_sel = tmp_sys_gpio_data->user_gpio_status.mul_sel; //从用户传进数据中读出功能数据 + gpio_status->pull = tmp_sys_gpio_data->user_gpio_status.pull; //从用户传进数据中读出pull数据 + gpio_status->drv_level = tmp_sys_gpio_data->user_gpio_status.drv_level; //从用户传进数据中读出驱动能力数据 + gpio_status->data = tmp_sys_gpio_data->user_gpio_status.data; //从用户传进数据中读出data数据 + } + else //当前读出寄存器实际的参数 + { + port_num_func = (port_num >> 3); + port_num_pull = (port_num >> 4); + + tmp_val1 = ((port_num - (port_num_func << 3)) << 2); + tmp_val2 = ((port_num - (port_num_pull << 4)) << 1); + gpio_status->mul_sel = (PIO_REG_CFG_VALUE(port, port_num_func)>>tmp_val1) & 0x07; //从硬件中读出功能寄存器 + gpio_status->pull = (PIO_REG_PULL_VALUE(port, port_num_pull)>>tmp_val2) & 0x03; //从硬件中读出pull寄存器 + gpio_status->drv_level = (PIO_REG_DLEVEL_VALUE(port, port_num_pull)>>tmp_val2) & 0x03; //从硬件中读出level寄存器 + if(gpio_status->mul_sel <= 1) + { + gpio_status->data = (PIO_REG_DATA_VALUE(port) >> port_num) & 0x01; //从硬件中读出data寄存器 + } + else + { + gpio_status->data = -1; + } + } + + break; + } + + return EGPIO_SUCCESS; +} +EXPORT_SYMBOL(gpio_get_one_pin_status); + +/* +********************************************************************************************************************** +* CSP_PIN_Set_One_Gpio_Status +* +* Description: +* 获取用户申请过的GPIO的某一个的状态 +* Arguments : +* p_handler : handler +* gpio_status : 保存用户数据的数组 +* gpio_name : 要操作的GPIO的名称 +* if_get_user_set_flag : 读取标志,表示读取用户设定数据或者是实际数据 +* Returns : +* +* Notes : +* +********************************************************************************************************************** +*/ + +__s32 gpio_set_one_pin_status(u32 p_handler, user_gpio_set_t *gpio_status, const char *gpio_name, __u32 if_set_to_current_input_status) +{ + char *tmp_buf; //转换成char类型 + __u32 group_count_max; //最大GPIO个数 + system_gpio_set_t *user_gpio_set, *tmp_sys_gpio_data; + user_gpio_set_t script_gpio; + volatile __u32 *tmp_addr; + __u32 port_num_func, port_num_pull; + __u32 port, port_num; + __u32 i, reg_val, tmp_val; + + //检查传进的句柄的有效性 + if((!p_handler) || (!gpio_name)) + { + return EGPIO_FAIL; + } + if((if_set_to_current_input_status) && (!gpio_status)) + { + return EGPIO_FAIL; + } + tmp_buf = (char *)p_handler; + group_count_max = *(int *)tmp_buf; + if(group_count_max <= 0) + { + return EGPIO_FAIL; + } + user_gpio_set = (system_gpio_set_t *)(tmp_buf + 16); + //读取用户数据 + //表示读取用户给定的数据 + for(i = 0; i < group_count_max; i++) + { + tmp_sys_gpio_data = user_gpio_set + i; //tmp_sys_gpio_data指向申请的GPIO空间 + if(strcmp(gpio_name, tmp_sys_gpio_data->gpio_name)) + { + continue; + } + + port = tmp_sys_gpio_data->port; //读出port数据 + port_num = tmp_sys_gpio_data->port_num; //读出port_num数据 + port_num_func = (port_num >> 3); + port_num_pull = (port_num >> 4); + + if(if_set_to_current_input_status) //根据当前用户设定修正 + { + //修改FUCN寄存器 + script_gpio.mul_sel = gpio_status->mul_sel; + script_gpio.pull = gpio_status->pull; + script_gpio.drv_level = gpio_status->drv_level; + script_gpio.data = gpio_status->data; + } + else + { + script_gpio.mul_sel = tmp_sys_gpio_data->user_gpio_status.mul_sel; + script_gpio.pull = tmp_sys_gpio_data->user_gpio_status.pull; + script_gpio.drv_level = tmp_sys_gpio_data->user_gpio_status.drv_level; + script_gpio.data = tmp_sys_gpio_data->user_gpio_status.data; + } + + if(script_gpio.mul_sel >= 0) + { + tmp_addr = PIO_REG_CFG(port, port_num_func); + reg_val = *tmp_addr; //修改FUNC寄存器 + tmp_val = (port_num - (port_num_func<<3))<<2; + reg_val &= ~(0x07 << tmp_val); + reg_val |= (script_gpio.mul_sel) << tmp_val; + *tmp_addr = reg_val; + } + //修改PULL寄存器 + if(script_gpio.pull >= 0) + { + tmp_addr = PIO_REG_PULL(port, port_num_pull); + reg_val = *tmp_addr; //修改FUNC寄存器 + tmp_val = (port_num - (port_num_pull<<4))<<1; + reg_val &= ~(0x03 << tmp_val); + reg_val |= (script_gpio.pull) << tmp_val; + *tmp_addr = reg_val; + } + //修改DLEVEL寄存器 + if(script_gpio.drv_level >= 0) + { + tmp_addr = PIO_REG_DLEVEL(port, port_num_pull); + reg_val = *tmp_addr; //修改FUNC寄存器 + tmp_val = (port_num - (port_num_pull<<4))<<1; + reg_val &= ~(0x03 << tmp_val); + reg_val |= (script_gpio.drv_level) << tmp_val; + *tmp_addr = reg_val; + } + //修改data寄存器 + if(script_gpio.mul_sel == 1) + { + if(script_gpio.data >= 0) + { + tmp_addr = PIO_REG_DATA(port); + reg_val = *tmp_addr; //修改DATA寄存器 + reg_val &= ~(0x01 << port_num); + reg_val |= (script_gpio.data & 0x01) << port_num; + *tmp_addr = reg_val; + } + } + + break; + } + + return EGPIO_SUCCESS; +} +EXPORT_SYMBOL(gpio_set_one_pin_status); + +/* +********************************************************************************************************************** +* CSP_GPIO_Set_One_PIN_IO_Status +* +* Description: +* 修改用户申请过的GPIO中的某一个IO口的,输入输出状态 +* Arguments : +* p_handler : handler +* if_set_to_output_status : 设置成输出状态还是输入状态 +* gpio_name : 要操作的GPIO的名称 +* Returns : +* +* Notes : +* +********************************************************************************************************************** +*/ +__s32 gpio_set_one_pin_io_status(u32 p_handler, __u32 if_set_to_output_status, const char *gpio_name) +{ + char *tmp_buf; //转换成char类型 + __u32 group_count_max; //最大GPIO个数 + system_gpio_set_t *user_gpio_set = NULL, *tmp_sys_gpio_data; + volatile __u32 *tmp_group_func_addr = NULL; + __u32 port, port_num, port_num_func; + __u32 i, reg_val; + + //检查传进的句柄的有效性 + if(!p_handler) + { + return EGPIO_FAIL; + } + if(if_set_to_output_status > 1) + { + return EGPIO_FAIL; + } + tmp_buf = (char *)p_handler; + group_count_max = *(int *)tmp_buf; + tmp_sys_gpio_data = (system_gpio_set_t *)(tmp_buf + 16); + if(group_count_max == 0) + { + return EGPIO_FAIL; + } + else if(group_count_max == 1) + { + user_gpio_set = tmp_sys_gpio_data; + } + else if(gpio_name) + { + for(i=0; i<group_count_max; i++) + { + if(strcmp(gpio_name, tmp_sys_gpio_data->gpio_name)) + { + tmp_sys_gpio_data ++; + continue; + } + user_gpio_set = tmp_sys_gpio_data; + break; + } + } + if(!user_gpio_set) + { + return EGPIO_FAIL; + } + + port = user_gpio_set->port; + port_num = user_gpio_set->port_num; + port_num_func = port_num >> 3; + + tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); + reg_val = *tmp_group_func_addr; + reg_val &= ~(0x07 << (((port_num - (port_num_func<<3))<<2))); + reg_val |= if_set_to_output_status << (((port_num - (port_num_func<<3))<<2)); + *tmp_group_func_addr = reg_val; + + return EGPIO_SUCCESS; +} +EXPORT_SYMBOL(gpio_set_one_pin_io_status); + +/* +********************************************************************************************************************** +* CSP_GPIO_Set_One_PIN_Pull +* +* Description: +* 修改用户申请过的GPIO中的某一个IO口的,PULL状态 +* Arguments : +* p_handler : handler +* if_set_to_output_status : 所设置的pull状态 +* gpio_name : 要操作的GPIO的名称 +* Returns : +* +* Notes : +* +********************************************************************************************************************** +*/ +__s32 gpio_set_one_pin_pull(u32 p_handler, __u32 set_pull_status, const char *gpio_name) +{ + char *tmp_buf; //转换成char类型 + __u32 group_count_max; //最大GPIO个数 + system_gpio_set_t *user_gpio_set = NULL, *tmp_sys_gpio_data; + volatile __u32 *tmp_group_pull_addr = NULL; + __u32 port, port_num, port_num_pull; + __u32 i, reg_val; + //检查传进的句柄的有效性 + if(!p_handler) + { + return EGPIO_FAIL; + } + if(set_pull_status >= 4) + { + return EGPIO_FAIL; + } + tmp_buf = (char *)p_handler; + group_count_max = *(int *)tmp_buf; + tmp_sys_gpio_data = (system_gpio_set_t *)(tmp_buf + 16); + if(group_count_max == 0) + { + return EGPIO_FAIL; + } + else if(group_count_max == 1) + { + user_gpio_set = tmp_sys_gpio_data; + } + else if(gpio_name) + { + for(i=0; i<group_count_max; i++) + { + if(strcmp(gpio_name, tmp_sys_gpio_data->gpio_name)) + { + tmp_sys_gpio_data ++; + continue; + } + user_gpio_set = tmp_sys_gpio_data; + break; + } + } + if(!user_gpio_set) + { + return EGPIO_FAIL; + } + + port = user_gpio_set->port; + port_num = user_gpio_set->port_num; + port_num_pull = port_num >> 4; + + tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); + reg_val = *tmp_group_pull_addr; + reg_val &= ~(0x03 << (((port_num - (port_num_pull<<4))<<1))); + reg_val |= (set_pull_status << (((port_num - (port_num_pull<<4))<<1))); + *tmp_group_pull_addr = reg_val; + + return EGPIO_SUCCESS; +} +EXPORT_SYMBOL(gpio_set_one_pin_pull); + +/* +********************************************************************************************************************** +* CSP_GPIO_Set_One_PIN_driver_level +* +* Description: +* 修改用户申请过的GPIO中的某一个IO口的,驱动能力 +* Arguments : +* p_handler : handler +* if_set_to_output_status : 所设置的驱动能力等级 +* gpio_name : 要操作的GPIO的名称 +* Returns : +* +* Notes : +* +********************************************************************************************************************** +*/ +__s32 gpio_set_one_pin_driver_level(u32 p_handler, __u32 set_driver_level, const char *gpio_name) +{ + char *tmp_buf; //转换成char类型 + __u32 group_count_max; //最大GPIO个数 + system_gpio_set_t *user_gpio_set = NULL, *tmp_sys_gpio_data; + volatile __u32 *tmp_group_dlevel_addr = NULL; + __u32 port, port_num, port_num_dlevel; + __u32 i, reg_val; + //检查传进的句柄的有效性 + if(!p_handler) + { + return EGPIO_FAIL; + } + if(set_driver_level >= 4) + { + return EGPIO_FAIL; + } + tmp_buf = (char *)p_handler; + group_count_max = *(int *)tmp_buf; + tmp_sys_gpio_data = (system_gpio_set_t *)(tmp_buf + 16); + + if(group_count_max == 0) + { + return EGPIO_FAIL; + } + else if(group_count_max == 1) + { + user_gpio_set = tmp_sys_gpio_data; + } + else if(gpio_name) + { + for(i=0; i<group_count_max; i++) + { + if(strcmp(gpio_name, tmp_sys_gpio_data->gpio_name)) + { + tmp_sys_gpio_data ++; + continue; + } + user_gpio_set = tmp_sys_gpio_data; + break; + } + } + if(!user_gpio_set) + { + return EGPIO_FAIL; + } + + port = user_gpio_set->port; + port_num = user_gpio_set->port_num; + port_num_dlevel = port_num >> 4; + + tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_dlevel); + reg_val = *tmp_group_dlevel_addr; + reg_val &= ~(0x03 << (((port_num - (port_num_dlevel<<4))<<1))); + reg_val |= (set_driver_level << (((port_num - (port_num_dlevel<<4))<<1))); + *tmp_group_dlevel_addr = reg_val; + + return EGPIO_SUCCESS; +} +EXPORT_SYMBOL(gpio_set_one_pin_driver_level); + +/* +********************************************************************************************************************** +* CSP_GPIO_Read_One_PIN_Value +* +* Description: +* 读取用户申请过的GPIO中的某一个IO口的端口的电平 +* Arguments : +* p_handler : handler +* gpio_name : 要操作的GPIO的名称 +* Returns : +* +* Notes : +* +********************************************************************************************************************** +*/ +__s32 gpio_read_one_pin_value(u32 p_handler, const char *gpio_name) +{ + char *tmp_buf; //转换成char类型 + __u32 group_count_max; //最大GPIO个数 + system_gpio_set_t *user_gpio_set = NULL, *tmp_sys_gpio_data; + __u32 port, port_num, port_num_func, func_val; + __u32 i, reg_val; + //检查传进的句柄的有效性 + if(!p_handler) + { + return EGPIO_FAIL; + } + tmp_buf = (char *)p_handler; + group_count_max = *(int *)tmp_buf; + tmp_sys_gpio_data = (system_gpio_set_t *)(tmp_buf + 16); + + if(group_count_max == 0) + { + return EGPIO_FAIL; + } + else if(group_count_max == 1) + { + user_gpio_set = tmp_sys_gpio_data; + } + else if(gpio_name) + { + for(i=0; i<group_count_max; i++) + { + if(strcmp(gpio_name, tmp_sys_gpio_data->gpio_name)) + { + tmp_sys_gpio_data ++; + continue; + } + user_gpio_set = tmp_sys_gpio_data; + break; + } + } + if(!user_gpio_set) + { + return EGPIO_FAIL; + } + + port = user_gpio_set->port; + port_num = user_gpio_set->port_num; + port_num_func = port_num >> 3; + + reg_val = PIO_REG_CFG_VALUE(port, port_num_func); + func_val = (reg_val >> ((port_num - (port_num_func<<3))<<2)) & 0x07; + if(func_val == 0) + { + reg_val = (PIO_REG_DATA_VALUE(port) >> port_num) & 0x01; + + return reg_val; + } + + return EGPIO_FAIL; +} +EXPORT_SYMBOL(gpio_read_one_pin_value); + +/* +********************************************************************************************************************** +* CSP_GPIO_Write_One_PIN_Value +* +* Description: +* 修改用户申请过的GPIO中的某一个IO口的端口的电平 +* Arguments : +* p_handler : handler +* value_to_gpio: 要设置的电平的电压 +* gpio_name : 要操作的GPIO的名称 +* Returns : +* +* Notes : +* +********************************************************************************************************************** +*/ +__s32 gpio_write_one_pin_value(u32 p_handler, __u32 value_to_gpio, const char *gpio_name) +{ + char *tmp_buf; //转换成char类型 + __u32 group_count_max; //最大GPIO个数 + system_gpio_set_t *user_gpio_set = NULL, *tmp_sys_gpio_data; + volatile __u32 *tmp_group_data_addr = NULL; + __u32 port, port_num, port_num_func, func_val; + __u32 i, reg_val; + //检查传进的句柄的有效性 + if(!p_handler) + { + return EGPIO_FAIL; + } + if(value_to_gpio >= 2) + { + return EGPIO_FAIL; + } + tmp_buf = (char *)p_handler; + group_count_max = *(int *)tmp_buf; + tmp_sys_gpio_data = (system_gpio_set_t *)(tmp_buf + 16); + + if(group_count_max == 0) + { + return EGPIO_FAIL; + } + else if(group_count_max == 1) + { + user_gpio_set = tmp_sys_gpio_data; + } + else if(gpio_name) + { + for(i=0; i<group_count_max; i++) + { + if(strcmp(gpio_name, tmp_sys_gpio_data->gpio_name)) + { + tmp_sys_gpio_data ++; + continue; + } + user_gpio_set = tmp_sys_gpio_data; + break; + } + } + if(!user_gpio_set) + { + return EGPIO_FAIL; + } + + port = user_gpio_set->port; + port_num = user_gpio_set->port_num; + port_num_func = port_num >> 3; + + reg_val = PIO_REG_CFG_VALUE(port, port_num_func); + func_val = (reg_val >> ((port_num - (port_num_func<<3))<<2)) & 0x07; + if(func_val == 1) + { + tmp_group_data_addr = PIO_REG_DATA(port); + reg_val = *tmp_group_data_addr; + reg_val &= ~(1 << port_num); + reg_val |= (value_to_gpio << port_num); + *tmp_group_data_addr = reg_val; + + return EGPIO_SUCCESS; + } + + return EGPIO_FAIL; +} +EXPORT_SYMBOL(gpio_write_one_pin_value); + diff --git a/lichee/linux-3.3/drivers/ata/ahci.h b/lichee/linux-3.3/drivers/ata/ahci.h index b175000..c2594dd 100644 --- a/lichee/linux-3.3/drivers/ata/ahci.h +++ b/lichee/linux-3.3/drivers/ata/ahci.h @@ -195,6 +195,9 @@ enum { PORT_FBS_EN = (1 << 0), /* Enable FBS */ /* hpriv->flags bits */ + +#define AHCI_HFLAGS(flags) .private_data = (void *)(flags) + AHCI_HFLAG_NO_NCQ = (1 << 0), AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */ AHCI_HFLAG_IGN_SERR_INTERNAL = (1 << 2), /* ignore SERR_INTERNAL */ @@ -210,6 +213,9 @@ enum { AHCI_HFLAG_NO_SNTF = (1 << 12), /* no sntf */ AHCI_HFLAG_NO_FPDMA_AA = (1 << 13), /* no FPDMA AA */ AHCI_HFLAG_YES_FBS = (1 << 14), /* force FBS cap on */ + AHCI_HFLAG_DELAY_ENGINE = (1 << 15), /* do not start engine on + port start (wait until + error-handling stage) */ /* ap->flags bits */ diff --git a/lichee/linux-3.3/drivers/ata/libahci.c b/lichee/linux-3.3/drivers/ata/libahci.c index 6d083e0..3591865 100644 --- a/lichee/linux-3.3/drivers/ata/libahci.c +++ b/lichee/linux-3.3/drivers/ata/libahci.c @@ -46,6 +46,8 @@ #include <linux/libata.h> #include "ahci.h" +#include <linux/slab.h> + static int ahci_skip_host_reset; int ahci_ignore_sss; EXPORT_SYMBOL_GPL(ahci_ignore_sss); @@ -744,6 +746,7 @@ static void ahci_power_down(struct ata_port *ap) static void ahci_start_port(struct ata_port *ap) { + struct ahci_host_priv *hpriv = ap->host->private_data; struct ahci_port_priv *pp = ap->private_data; struct ata_link *link; struct ahci_em_priv *emp; @@ -753,6 +756,10 @@ static void ahci_start_port(struct ata_port *ap) /* enable FIS reception */ ahci_start_fis_rx(ap); + /* enable DMA */ + if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE)) + ahci_start_engine(ap); + /* turn on LEDs */ if (ap->flags & ATA_FLAG_EM) { ata_for_each_link(link, ap, EDGE) { @@ -2069,11 +2076,7 @@ static int ahci_port_start(struct ata_port *ap) rx_fis_sz = AHCI_RX_FIS_SZ; } - //mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL); - //danielwang - mem = kmalloc(dma_sz, GFP_DMA | GFP_KERNEL); - mem_dma = __pa(mem); - //printk("dmam_alloc_coherent mem = 0x%x, size = 0x%x, mem_dma=0x%x\n", (unsigned int)mem, (unsigned int)dma_sz, (unsigned int)mem_dma); + mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL); if (!mem) return -ENOMEM; memset(mem, 0, dma_sz); diff --git a/lichee/linux-3.3/drivers/ata/sw_ahci_platform.c b/lichee/linux-3.3/drivers/ata/sw_ahci_platform.c index 1cc2206..35dbb45 100755 --- a/lichee/linux-3.3/drivers/ata/sw_ahci_platform.c +++ b/lichee/linux-3.3/drivers/ata/sw_ahci_platform.c @@ -1,25 +1,31 @@ /* -************************************************************************************* -* Linux -* AHCI SATA platform driver -* -* (c) Copyright 2006-2010, All winners Co,Ld. -* All Rights Reserved -* -* File Name : sw_ahci_platform.c -* -* Author : danielwang -* -* Description : SATA Host Controller Driver for AW1623 Platform -* -* Notes : -* -* History : -* <author> <time> <version > <desc> -* danielwang 2011-6-29 1.0 create this file -* -************************************************************************************* -*/ + * drivers/ata/sw_ahci_platform.c + * + * (C) Copyright 2007-2012 + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Daniel Wang <danielwang@allwinnertech.com> + * + * Based on ahci_platform.c AHCI SATA platform driver + * + * Copyright 2004-2005 Red Hat, Inc. + * Jeff Garzik <jgarzik@pobox.com> + * Copyright 2010 MontaVista Software, LLC. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ #include <linux/kernel.h> #include <linux/gfp.h> @@ -34,7 +40,6 @@ #include <linux/clk.h> #include <mach/sys_config.h> -#include <mach/gpio.h> #include "sw_ahci_platform.h" static struct scsi_host_template ahci_platform_sht = { @@ -66,89 +71,89 @@ static int sw_ahci_phy_init(unsigned int base) unsigned int tmp; const unsigned int timeout_val = 0x100000; unsigned int timeout = timeout_val; - + for(tmp=0; tmp<0x1000; tmp++); - + SW_AHCI_ACCESS_LOCK(base, 0); - + tmp = ahci_readl(base, SW_AHCI_PHYCS1R_OFFSET); - tmp |= (0x1<<19); + tmp |= (0x1<<19); ahci_writel(base, SW_AHCI_PHYCS1R_OFFSET, tmp); - + tmp = ahci_readl(base, SW_AHCI_PHYCS0R_OFFSET); - tmp |= 0x1<<23; - tmp |= 0x1<<18; - tmp &= ~(0x7<<24); - tmp |= 0x5<<24; + tmp |= 0x1<<23; + tmp |= 0x1<<18; + tmp &= ~(0x7<<24); + tmp |= 0x5<<24; ahci_writel(base, SW_AHCI_PHYCS0R_OFFSET, tmp); - + tmp = ahci_readl(base, SW_AHCI_PHYCS1R_OFFSET); - tmp &= ~(0x3<<16); - tmp |= (0x2<<16); + tmp &= ~(0x3<<16); + tmp |= (0x2<<16); tmp &= ~(0x1f<<8); - tmp |= (6<<8); - tmp &= ~(0x3<<6); - tmp |= (2<<6); + tmp |= (6<<8); + tmp &= ~(0x3<<6); + tmp |= (2<<6); ahci_writel(base, SW_AHCI_PHYCS1R_OFFSET, tmp); - + tmp = ahci_readl(base, SW_AHCI_PHYCS1R_OFFSET); - tmp |= (0x1<<28); - tmp |= (0x1<<15); + tmp |= (0x1<<28); + tmp |= (0x1<<15); ahci_writel(base, SW_AHCI_PHYCS1R_OFFSET, tmp); - + tmp = ahci_readl(base, SW_AHCI_PHYCS1R_OFFSET); - tmp &= ~(0x1<<19); + tmp &= ~(0x1<<19); ahci_writel(base, SW_AHCI_PHYCS1R_OFFSET, tmp); - + tmp = ahci_readl(base, SW_AHCI_PHYCS0R_OFFSET); - tmp &= ~(0x7<<20); - tmp |= (0x03<<20); + tmp &= ~(0x7<<20); + tmp |= (0x03<<20); ahci_writel(base, SW_AHCI_PHYCS0R_OFFSET, tmp); - + tmp = ahci_readl(base, SW_AHCI_PHYCS2R_OFFSET); - tmp &= ~(0x1f<<5); - tmp |= (0x19<<5); + tmp &= ~(0x1f<<5); + tmp |= (0x19<<5); ahci_writel(base, SW_AHCI_PHYCS2R_OFFSET, tmp); - + for(tmp=0; tmp<0x1000; tmp++); - + tmp = ahci_readl(base, SW_AHCI_PHYCS0R_OFFSET); - tmp |= 0x1<<19; + tmp |= 0x1<<19; ahci_writel(base, SW_AHCI_PHYCS0R_OFFSET, tmp); - + timeout = timeout_val; do{ tmp = ahci_readl(base, SW_AHCI_PHYCS0R_OFFSET); timeout --; if(!timeout) break; - }while((tmp&(0x7<<28))!=(0x02<<28)); - + }while((tmp&(0x7<<28))!=(0x02<<28)); + if(!timeout) { printk("SATA AHCI Phy Power Failed!!\n"); } - + tmp = ahci_readl(base, SW_AHCI_PHYCS2R_OFFSET); - tmp |= 0x1<<24; + tmp |= 0x1<<24; ahci_writel(base, SW_AHCI_PHYCS2R_OFFSET, tmp); - + timeout = timeout_val; do{ tmp = ahci_readl(base, SW_AHCI_PHYCS2R_OFFSET); timeout --; if(!timeout) break; - }while(tmp&(0x1<<24)); - + }while(tmp&(0x1<<24)); + if(!timeout) { printk("SATA AHCI Phy Calibration Failed!!\n"); } - + for(tmp=0; tmp<0x3000; tmp++); - + SW_AHCI_ACCESS_LOCK(base, 0x07); - - return 0; + + return 0; } static int sw_ahci_start(struct device *dev, void __iomem *addr) @@ -156,16 +161,7 @@ static int sw_ahci_start(struct device *dev, void __iomem *addr) struct clk *hclk; struct clk *mclk; u32 pio_hdle = 0; - int ctrl = 0; int rc = 0; - - script_parser_fetch(sw_ahci_para_name, sw_ahci_used_name, &ctrl, sizeof(int)); - if(!ctrl) - { - dev_err(dev, "AHCI is disable\n"); - rc = -EINVAL; - goto err2; - } /*Enable mclk and hclk for AHCI*/ mclk = clk_get(dev, sw_ahci_mclk_name); @@ -175,7 +171,7 @@ static int sw_ahci_start(struct device *dev, void __iomem *addr) rc = -EINVAL; goto err2; } - + hclk = clk_get(dev, sw_ahci_hclk_name); if (IS_ERR(hclk)) { @@ -183,25 +179,25 @@ static int sw_ahci_start(struct device *dev, void __iomem *addr) rc = -EINVAL; goto err1; } - + /*Enable SATA Clock in SATA PLL*/ ahci_writel(CCMU_PLL6_VBASE, 0, ahci_readl(CCMU_PLL6_VBASE, 0)|(0x1<<14)); clk_enable(mclk); clk_enable(hclk); - + sw_ahci_phy_init((unsigned int)addr); - pio_hdle = sw_gpio_request_ex(sw_ahci_para_name, NULL); - if(pio_hdle) + pio_hdle = gpio_request_ex(sw_ahci_para_name, NULL); + if(pio_hdle) { - sw_gpio_write_one_pin_value(pio_hdle, 1, sw_ahci_gpio_name); - sw_gpio_release(pio_hdle, 2); + gpio_write_one_pin_value(pio_hdle, 1, sw_ahci_gpio_name); + gpio_release(pio_hdle, 2); } - + clk_put(hclk); err1: - clk_put(mclk); -err2: + clk_put(mclk); +err2: return rc; } @@ -211,7 +207,7 @@ static void sw_ahci_stop(struct device *dev) struct clk *mclk; u32 pio_hdle = 0; int rc = 0; - + mclk = clk_get(dev, sw_ahci_mclk_name); if (IS_ERR(mclk)) { @@ -219,7 +215,7 @@ static void sw_ahci_stop(struct device *dev) rc = -EINVAL; goto err2; } - + hclk = clk_get(dev, sw_ahci_hclk_name); if (IS_ERR(hclk)) { @@ -228,13 +224,13 @@ static void sw_ahci_stop(struct device *dev) goto err1; } - pio_hdle = sw_gpio_request_ex(sw_ahci_para_name, NULL); - if(pio_hdle) + pio_hdle = gpio_request_ex(sw_ahci_para_name, NULL); + if(pio_hdle) { - sw_gpio_write_one_pin_value(pio_hdle, 0, sw_ahci_gpio_name); - sw_gpio_release(pio_hdle, 2); + gpio_write_one_pin_value(pio_hdle, 0, sw_ahci_gpio_name); + gpio_release(pio_hdle, 2); } - + /*Disable mclk and hclk for AHCI*/ clk_disable(mclk); clk_disable(hclk); @@ -252,7 +248,7 @@ static struct ata_port_info sw_ahci_port_info = { //.mwdma_mask = , .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, - .private_data = (void*)(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI + .private_data = (void*)(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ), }; @@ -262,13 +258,20 @@ static struct ahci_platform_data sw_ahci_platform_data = { .exit = sw_ahci_stop, }; +void sw_ahci_release(struct device *dev) +{ + /* FILL ME! */ +} + static struct platform_device sw_ahci_device = { .name = "sw_ahci", .id = 0, .dev = { .platform_data = &sw_ahci_platform_data, + .release = &sw_ahci_release, + .coherent_dma_mask = DMA_BIT_MASK(32), }, - + .num_resources = ARRAY_SIZE(sw_ahci_resources), .resource = sw_ahci_resources, }; @@ -421,7 +424,7 @@ static int __devexit sw_ahci_remove(struct platform_device *pdev) void sw_ahci_dump_reg(struct device *dev) { struct ata_host *host = dev_get_drvdata(dev); - struct ahci_host_priv *hpriv = host->private_data; + struct ahci_host_priv *hpriv = host->private_data; u32 base = (u32)hpriv->mmio; int i = 0; @@ -434,7 +437,7 @@ void sw_ahci_dump_reg(struct device *dev) static int sw_ahci_suspend(struct device *dev) { - + printk("sw_ahci_platform: sw_ahci_suspend\n"); //danielwang //sw_ahci_dump_reg(dev); @@ -447,12 +450,12 @@ extern int ahci_hardware_recover_for_controller_resume(struct ata_host *host); static int sw_ahci_resume(struct device *dev) { struct ata_host *host = dev_get_drvdata(dev); - struct ahci_host_priv *hpriv = host->private_data; - + struct ahci_host_priv *hpriv = host->private_data; + printk("sw_ahci_platform: sw_ahci_resume\n"); //danielwang sw_ahci_start(dev, hpriv->mmio); - //sw_ahci_dump_reg(dev); + //sw_ahci_dump_reg(dev); ahci_hardware_recover_for_controller_resume(host); @@ -483,14 +486,30 @@ static struct platform_driver sw_ahci_driver = { static int __init sw_ahci_init(void) { - platform_device_register(&sw_ahci_device); - return platform_driver_probe(&sw_ahci_driver, sw_ahci_probe); + int rc, ctrl = 0; + script_parser_fetch(sw_ahci_para_name, + sw_ahci_used_name, &ctrl, sizeof(int)); + if (!ctrl) { + pr_warn("AHCI is disabled in script.bin\n"); + return -ENODEV; + } + + rc = platform_device_register(&sw_ahci_device); + if (rc) + return rc; + + rc = platform_driver_probe(&sw_ahci_driver, sw_ahci_probe); + if (rc) + platform_device_unregister(&sw_ahci_device); + + return rc; } module_init(sw_ahci_init); static void __exit sw_ahci_exit(void) { platform_driver_unregister(&sw_ahci_driver); + platform_device_unregister(&sw_ahci_device); } module_exit(sw_ahci_exit); diff --git a/lichee/linux-3.3/drivers/ata/sw_ahci_platform.h b/lichee/linux-3.3/drivers/ata/sw_ahci_platform.h index 45abd76..fb35f5b 100755 --- a/lichee/linux-3.3/drivers/ata/sw_ahci_platform.h +++ b/lichee/linux-3.3/drivers/ata/sw_ahci_platform.h @@ -1,20 +1,38 @@ /* - * AHCI SATA platform driver + * drivers/ata/sw_ahci_platform.h * + * (C) Copyright 2007-2012 + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Daniel Wang <danielwang@allwinnertech.com> + * + * Based on ahci_platform.h + * * Copyright 2004-2005 Red Hat, Inc. * Jeff Garzik <jgarzik@pobox.com> * Copyright 2010 MontaVista Software, LLC. * Anton Vorontsov <avorontsov@ru.mvista.com> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA */ #ifndef _SW_AHCI_PLATFORM_H #define _SW_AHCI_PLATFORM_H +#include <mach/irqs.h> + #define ahci_readb(base,offset) (*((volatile unsigned char*)((base)+(offset)))) #define ahci_readw(base,offset) (*((volatile unsigned short*)((base)+(offset)))) #define ahci_readl(base,offset) (*((volatile unsigned int*)((base)+(offset)))) @@ -48,9 +66,9 @@ #define SW_AHCI_P0PHYCR_OFFSET 0x0178 #define SW_AHCI_P0PHYSR_OFFSET 0x017C -#define SW_AHCI_ACCESS_LOCK(base,x) (*((volatile unsigned int *)((base)+SW_AHCI_RWCR_OFFSET)) = (x)) +#define SW_AHCI_ACCESS_LOCK(base,x) (*((volatile unsigned int *)((base)+SW_AHCI_RWCR_OFFSET)) = (x)) -#define INTC_IRQNO_AHCI 56 +#define INTC_IRQNO_AHCI AW_IRQ_SATA #define CCMU_PLL6_VBASE 0xF1C20028 diff --git a/lichee/tools/pack/chips/sun7i/configs/android/wing-k70/sys_config.fex b/lichee/tools/pack/chips/sun7i/configs/android/wing-k70/sys_config.fex index e50d6e6..15eb781 100755 --- a/lichee/tools/pack/chips/sun7i/configs/android/wing-k70/sys_config.fex +++ b/lichee/tools/pack/chips/sun7i/configs/android/wing-k70/sys_config.fex @@ -762,7 +762,7 @@ tvin_channel_num = 4 ;------------------------------------------------------------------------------- [sata_para] sata_used = 1 -sata_power_en = +sata_power_en = port ![]() ;------------------------------------------------------------------------------- -- 1.7.9.5 格式化硬盘脚本文件: #! /system/bin/sh ################################################################################ #Title: fdisk_shell.sh #Description: fdisk disk #Platform:A20 #Copyright: Copyright (c) 2013 #Company:< wangjian1937@live.cn> #Author: wangjian #Version: 1.0 #Date: 2013.11.18 /system/bin/busybox mkdir -p /mnt/sdcard/fdisk /system/bin/busybox chmod 777 /mnt/sdcard/fdisk /system/bin/busybox touch /mnt/sdcard/fdisk/2 /system/bin/busybox touch /mnt/sdcard/fdisk/1.0 /system/bin/busybox touch /mnt/sdcard/fdisk/1.1 /system/bin/busybox touch /mnt/sdcard/fdisk/1.2 /system/bin/ll /mnt/sata/ umount /mnt/sata sleep 1 #########################fdisk operation######################################## echo "n p 1 1 t L 7 w" >/mnt/sdcard/fdisk/2 ###########################fdisk disk########################################### /system/bin/busybox fdisk /dev/block/vold/sata/8:0 -l | /system/bin/busybox grep dev > /mnt/sdcard/fdisk/1.0 /system/bin/busybox fdisk /dev/block/vold/sata/8:0 -l | /system/bin/busybox grep dev | /system/bin/busybox sed -n '1,/(LBA)/p' | /system/bin/busybox sed '1d' | /system/bin/busybox awk '{print $1}' | /system/bin/busybox sed 's#/dev/block/vold/sata/8:0p##g' > /mnt/sdcard/fdisk/1.1 /system/bin/busybox fdisk /dev/block/vold/sata/8:0 -l | /system/bin/busybox grep dev | /system/bin/busybox sed -n '/(LBA)/,$p' | /system/bin/busybox sed '1d' | /system/bin/busybox awk '{print $1}' | /system/bin/busybox sed 's#/dev/block/vold/sata/8:0p##g' > /mnt/sdcard/fdisk/1.2 echo "/mnt/sdcard/fdisk/1.0" cat /mnt/sdcard/fdisk/1.0 echo "/mnt/sdcard/fdisk/1.1" cat /mnt/sdcard/fdisk/1.1 echo "/mnt/sdcard/fdisk/1.2" cat /mnt/sdcard/fdisk/1.2 y=`cat /mnt/sdcard/fdisk/1.1 | /system/bin/busybox wc -l` echo $y i=1 while [[ "$i" -lt "$y" ]];do j=`/system/bin/busybox sed -n "${i}p" /mnt/sdcard/fdisk/1.1` echo "d ${j} w" >/mnt/sdcard/fdisk/2_"${i}" echo "/mnt/sdcard/fdisk/2_"${i}"" umount /mnt/sata/8_"${j}" cat /mnt/sdcard/fdisk/2_"${i}" echo "delete the "${j}" partition....." /system/bin/busybox fdisk /dev/block/vold/sata/8:0 < /mnt/sdcard/fdisk/2_"${i}" let i=i+1 done ############ if [[ -z "`grep "(LBA)" /mnt/sdcard/fdisk/1.0`" ]];then j=`/system/bin/busybox sed -n "${i}p" /mnt/sdcard/fdisk/1.1` echo "d w" >/mnt/sdcard/fdisk/2_"${i}" fi ############# if [[ -n "`grep "(LBA)" /mnt/sdcard/fdisk/1.0`" ]];then j=`/system/bin/busybox sed -n "${i}p" /mnt/sdcard/fdisk/1.1` echo "d ${j} w" >/mnt/sdcard/fdisk/2_"${i}" fi ########delete the last partition######################### if [[ "$y" -ne 0 ]];then echo "/mnt/sdcard/fdisk/2_"${i}"" umount /mnt/sata/8_"${j}" cat /mnt/sdcard/fdisk/2_"${i}" echo "delete the last partition....." /system/bin/busybox fdisk /dev/block/vold/sata/8:0 < /mnt/sdcard/fdisk/2_"${i}" fi #####################umount the least partition############# if [[ -n "`grep "(LBA)" /mnt/sdcard/fdisk/1.0`" ]];then y=`cat /mnt/sdcard/fdisk/1.2 | /system/bin/busybox wc -l` i=1 while [[ "$i" -le "$y" ]];do j=`/system/bin/busybox sed -n "${i}p" /mnt/sdcard/fdisk/1.2` echo "umount /mnt/sata/8_"${j}"" umount /mnt/sata/8_"${j}" let i=i+1 done fi #################mkfs###################################### echo "fdisk....." /system/bin/busybox fdisk /dev/block/vold/sata/8:0 < /mnt/sdcard/fdisk/2 echo "umount /mnt/sata." umount /mnt/sata sleep 1 echo "mkfs....." mkntfs -f -L sata /dev/block/vold/sata/8:1 echo "fs has done!" echo "mount...." #mount -t ntfs /dev/block/vold/sata/8:1 /mnt/sata reboot |
转载于:https://my.oschina.net/u/1176566/blog/284779