frescale imx6 gpioGPIO管理设计规范

来源:互联网 发布:男士淡斑清洁面膜知乎 编辑:程序博客网 时间:2024/06/07 17:11

1. 概论

freescale imx6平台的GPIO是多映射的,很多GPIO可以被复用成多种外设,同时又有多个GPIO端口可以映射成同一功能口,这是一种网状的映射。每当imx6有新的硬件出来后,大部分的外设重新分配了下,GPIO配置很不好管理。经常有GPIO冲突的现象,造成一些难以察觉到的错误。

2.设计思路

性能要求:

方便性,在booter中一次性配好,kernel直接利用这个配置文件,初始化相应的GPIO,一步到位不要分散的去配置GPIO

可调试性,每个模块的使用者必须申请相关的权限才可以使用,sys负责记录这些信息,方便出错的时候察看。

可扩展性,因为是通过配置文件的形式来配置GPIO的,只需要在booter中添加配置即可。

3.GPIO在内存中的配置表

3.1位置

在最高内存的sram_map_t区域下面开一个32K的内存区域,用于存放内存配置表。

3.2主要数据结构

structgpio_desc_skeleton

结构体说明(32K

名称

类型

说明

head_flag

u32

0x524c1234

version

u32

0x1

num

u32

structgpio_desc_body[]中实际元素的个数

reserved

u32[4]

保留

body

structgpio_desc_body [818];

此数组最大的个数为(32K-48)/sizeof(structgpio_desc_body) = 682

checksum

u32

棕色区域的crc32



structgpio_desc_body

结构体说明(48字节)

名称

类型

说明

type

u8

enum{gpio_init, gpio_dynamic¹};

default_val

u8

enum{val_low, val_high, val_hardware};

当值为val_low或者val_high的时候,表明做GPIOval_hardware是做外设功能。

if_pad_cfg

u16

在初始化(BOOTER第一次处理总的配置数组的时候)的时候是否打pad1则在使用的时候再打,0BOOTER初始化的时候打pad

who_use

char[16]

用于记录是哪个模块或者文件使用了GPIO

gpio_nr

int

IMX_GPIO_NR(x,y)

pad_cfg

iomux_v3_cfg_t(u64)

GPIOpadiomux控制

hardware_desc

char[16]

硬件功能描述,如”uart1_tx”等。


gpio_initgpio_dynamic是两种gpio的类型,当类型为gpio_init的时候,是不允许用户模式(userspace)在初始化完了后再更改pad_cfgdefault_valgpio_dynamicimx6_gpio.c驱动中管理的GPIO,可以动态改pad_cfgdefault_val

4.内核中GPIO管理优化

4.1内核中旧的打pad的函数。

intmxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad);

旧接口的不足:不具备调试功能,单纯将某GPIO设置成某功能。当多个文件对有冲突的GPIO设定成不同的功能的时候,起作用的是最后一次设定,但是往往重复的设置是意外,我们并不希望的功能。难以察觉问题。

4.2修改后的打pad的函数。

int mxc_iomux_v3_setup_pad(struct gpio_desc_body *desc, int permission);

permission的值有两种enum{per_user, per_kernel, per_root};

permissionper_user的时候,如果desc->typegpio_init,则返回-1,并警告。

permissionper_kernel的时候,如果desc->typegpio_init,则返回-1,并警告。

permissionper_root的时候,是允许任何操作的。但是只限于第一次统一初始化gpio的时候用到。

4.3修改记录

每一次有效的修改需要被记录在sys中特定的文件里。

5. 代码

可以在我的github下载

点击打开链接

gpio_control.h

#ifndef __YWWH_GPIO_CONTROL_H_#define __YWWH_GPIO_CONTROL_H#if !__BOOTER_CODE#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))#endif#define GPIO_TABLE_ADDR 0x4ff00000//#define GPIO_TABLE_ADDR 0x4FFE8000#define GPIO_TABLE_MAP_SIZE                    0x00008000struct gpio_desc_body {    u8 type;    u8 default_val;    u16 if_pad_cfg; // if 0, need pad, if 1 needn't pad    char who_use[16];    int gpio_nr;    iomux_v3_cfg_t pad_cfg;    char hardware_desc[16];};#define DESC_BODY_NUM  (GPIO_TABLE_MAP_SIZE - sizeof(u32)*5)/sizeof(struct gpio_desc_body)/* the struct is 32K bytes */struct gpio_desc_skeleton {    u32 head_flag;    u32 version;    u32 num;    u32 reserved[2];    struct gpio_desc_body body[DESC_BODY_NUM];    u32 checksum;};/* * struct gpio_desc_body::default_val * *  val_low : output low level *  val_high : output high level *  val_hardware : use hardware func, not gpio mode. */enum {val_low, val_high, val_hardware};enum {    pad_cfg,    dont_pad_cfg};enum {    per_user,    per_kernel,    per_root};enum {    gpio_init,    gpio_dynamic};# if !__BOOTER_CODEtypedef enum {    e_ok,    e_invalid_parameters,    e_insufficient_buffer,    e_object_not_exist,    e_insufficient_room,    e_io_fail,    e_no_permission,    e_data_corrupt,    e_system_busy,    e_too_many,    e_not_implement,    e_not_support,    e_out_of_ram,    e_reach_border,    e_alignment_required,    e_hardware_required,    e_unbelievable,    e_init}api_return_code_t;# endiflong mxc_iomux_v3_setup_pad(struct gpio_desc_body *desc, int permission);#endif

gpio_control.c

/* * <c> copyright ShenZhen Yuwei Ltd. * Author: King 2016.4.27 */#define __BOOTER_CODE 1#define __LINUX_KERNEL 0#define __LINUX_APP   0#define __debug__   1# if __BOOTER_CODE#include <common.h>#include <asm-arm/arch-mx6/iomux-v3.h>#include <asm-arm/arch-mx6/gpio.h>#include <asm-arm/arch-mx6/mx6dl_pins.h>#include <asm/io.h>#include "../libra/libra.h"//# elif __LINUX_KERNEL//# else // linux app#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <sys/mman.h>typedef unsigned int u32;typedef unsigned short u16;typedef unsigned char u8;typedef unsigned long long iomux_v3_cfg_t;# endif#include "ywwh_gpio_control.h"#if __BOOTER_CODEstruct gpio_desc_body desc_list[1] = {    /**     *  hardware     */    // uart    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(6, 17), MX6DL_PAD_SD3_DAT7__UART1_TXD, "UART1_TXD"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(6, 18), MX6DL_PAD_SD3_DAT6__UART1_RXD, "UART1_RXD"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(7, 1), MX6DL_PAD_SD3_DAT4__UART2_RXD, "UART2_RXD"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(7, 0), MX6DL_PAD_SD3_DAT5__UART2_TXD, "UART2_TXD"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(7, 2), MX6DL_PAD_SD3_CMD__UART2_CTS, "UART2_CTS"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(7, 3), MX6DL_PAD_SD3_CLK__UART2_RTS, "UART2_RTS"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(3, 24), MX6DL_PAD_EIM_D24__UART3_TXD, "UART3_TXD"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(3, 25), MX6DL_PAD_EIM_D25__UART3_RXD, "UART3_RXD"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 7), MX6DL_PAD_KEY_ROW0__UART4_RXD, "UART4_RXD"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 6), MX6DL_PAD_KEY_COL0__UART4_TXD, "UART4_TXD"},    // i2c    {gpio_dynamic, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 26), MX6DL_PAD_CSI0_DAT8__I2C1_SDA, "I2C1_SDA"},    {gpio_dynamic, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 27), MX6DL_PAD_CSI0_DAT9__I2C1_SCL, "I2C1_SCL"},    {gpio_dynamic, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 13), MX6DL_PAD_KEY_ROW3__I2C2_SDA, "I2C2_SDA"},    {gpio_dynamic, val_hardware, 0, "BOOTER", IMX_GPIO_NR(2, 30), MX6DL_PAD_EIM_EB2__I2C2_SCL, "I2C2_SCL"},    {gpio_dynamic, val_hardware, 0, "BOOTER", IMX_GPIO_NR(1, 3), MX6DL_PAD_GPIO_3__I2C3_SCL, "I2C3_SCL"},    {gpio_dynamic, val_hardware, 0, "BOOTER", IMX_GPIO_NR(1, 6), MX6DL_PAD_GPIO_6__I2C3_SDA, "I2C3_SDA"},    // spi    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 6), MX6DL_PAD_KEY_COL0__ECSPI1_SCLK, "ECSPI1_SCLK"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 8), MX6DL_PAD_KEY_COL1__ECSPI1_MISO, "ECSPI1_MISO"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 7), MX6DL_PAD_KEY_ROW0__ECSPI1_MOSI, "ECSPI1_MOSI"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 9), MX6DL_PAD_KEY_ROW1__ECSPI1_SS0, "ECSPI1_SS0"},    // emmc <sdio4>    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(7, 10), MX6DL_PAD_SD4_CLK__USDHC4_CLK, "USDHC4_CLK"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(7, 9), MX6DL_PAD_SD4_CMD__USDHC4_CMD, "USDHC4_CMD"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(2, 8), MX6DL_PAD_SD4_DAT0__USDHC4_DAT0, "USDHC4_DAT0"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(2, 9), MX6DL_PAD_SD4_DAT1__USDHC4_DAT1, "USDHC4_DAT1"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(2, 10), MX6DL_PAD_SD4_DAT2__USDHC4_DAT2, "USDHC4_DAT2"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(2, 11), MX6DL_PAD_SD4_DAT3__USDHC4_DAT3, "USDHC4_DAT3"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(2, 12), MX6DL_PAD_SD4_DAT4__USDHC4_DAT4, "USDHC4_DAT4"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(2, 13), MX6DL_PAD_SD4_DAT5__USDHC4_DAT5, "USDHC4_DAT5"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(2, 14), MX6DL_PAD_SD4_DAT6__USDHC4_DAT6, "USDHC4_DAT6"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(2, 15), MX6DL_PAD_SD4_DAT7__USDHC4_DAT7, "USDHC4_DAT7"},    // sdio2    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 10), MX6DL_PAD_SD2_CLK__USDHC2_CLK, "USDHC2_CLK"},    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 11), MX6DL_PAD_SD2_CMD__USDHC2_CMD, "USDHC2_CMD"},    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 15), MX6DL_PAD_SD2_DAT0__USDHC2_DAT0, "USDHC2_DAT0"},    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 14), MX6DL_PAD_SD2_DAT1__USDHC2_DAT1, "USDHC2_DAT1"},    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 13), MX6DL_PAD_SD2_DAT2__USDHC2_DAT2, "USDHC2_DAT2"},    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 12), MX6DL_PAD_SD2_DAT3__USDHC2_DAT3, "USDHC2_DAT3"},    // sdio1    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 20), MX6DL_PAD_SD1_CLK__USDHC1_CLK, "USDHC1_CLK"},    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 18), MX6DL_PAD_SD1_CMD__USDHC1_CMD, "USDHC1_CMD"},    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 16), MX6DL_PAD_SD1_DAT0__USDHC1_DAT0, "USDHC1_DAT0"},    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 17), MX6DL_PAD_SD1_DAT1__USDHC1_DAT1, "USDHC1_DAT1"},    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 19), MX6DL_PAD_SD1_DAT2__USDHC1_DAT2, "USDHC1_DAT2"},    {gpio_dynamic, val_hardware, 1, "BOOTER", IMX_GPIO_NR(1, 21), MX6DL_PAD_SD1_DAT3__USDHC1_DAT3, "USDHC1_DAT3"},    // audio    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 22), MX6DL_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC, "AUD3_TXC"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 23), MX6DL_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD, "AUD3_TXD"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 24), MX6DL_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS, "AUD3_TXFS"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 25), MX6DL_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD, "AUD3_RXD"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 22), MX6DL_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC, "AUD3_TXC"},    // display    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 16), MX6DL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, "IPU1_DI0_CLK"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 18), MX6DL_PAD_DI0_PIN2__IPU1_DI0_PIN2, "IPU1_DI0_PIN2"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 21), MX6DL_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0, "DISP0_DAT_0"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 22), MX6DL_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1, "DISP0_DAT_1"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 23), MX6DL_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2, "DISP0_DAT_2"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 25), MX6DL_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4, "DISP0_DAT_4"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 28), MX6DL_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7, "DISP0_DAT_7"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 29), MX6DL_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8, "DISP0_DAT_8"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 30), MX6DL_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9, "DISP0_DAT_9"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 30), MX6DL_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10, "DISP0_DAT_10"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(4, 31), MX6DL_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11, "DISP0_DAT_11"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 6), MX6DL_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12, "DISP0_DAT_12"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 8), MX6DL_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14, "DISP0_DAT_14"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 9), MX6DL_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15, "DISP0_DAT_15"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 10), MX6DL_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16, "DISP0_DAT_16"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 11), MX6DL_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17, "DISP0_DAT_17"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 12), MX6DL_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18, "DISP0_DAT_18"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 13), MX6DL_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19, "DISP0_DAT_19"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 14), MX6DL_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20, "DISP0_DAT_20"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 15), MX6DL_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21, "DISP0_DAT_21"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 22), MX6DL_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22, "DISP0_DAT_22"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(5, 17), MX6DL_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23, "DISP0_DAT_23"},    // USB    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(1, 1), MX6DL_PAD_GPIO_1__USBOTG_ID, "USBOTG_ID"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(3, 21), MX6DL_PAD_EIM_D21__USBOH3_USBOTG_OC, "USBOTG_OC"},    {gpio_init, val_hardware, 0, "BOOTER", IMX_GPIO_NR(3, 30), MX6DL_PAD_EIM_D30__USBOH3_USBH1_OC, "USBH1_OC"},    /*     * gpio     */    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(4, 29), MX6DL_PAD_DISP0_DAT8__GPIO_4_29, "SD POW"}, // enable    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(4, 18), MX6DL_PAD_DI0_PIN2__GPIO_4_18, "FM POW"}, // disable    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(4, 16), MX6DL_PAD_DI0_DISP_CLK__GPIO_4_16, "FM Control, reserved"},    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(4, 21), MX6DL_PAD_DISP0_DAT0__GPIO_4_21, "MIC SW1"}, //    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(4, 22), MX6DL_PAD_DISP0_DAT1__GPIO_4_22, "MIC SW2"}, // disable    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(4, 17), MX6DL_PAD_DI0_PIN15__GPIO_4_17, "BT POW"}, // disable    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(4, 19), MX6DL_PAD_DI0_PIN3__GPIO_4_19, "BT RESET"}, // disable    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(4, 23), MX6DL_PAD_DISP0_DAT2__GPIO_4_23, "GSM RESET"}, // disable    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(4, 25), MX6DL_PAD_DISP0_DAT4__GPIO_4_25, "GSM SLEEP"}, // disable    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(4, 29), MX6DL_PAD_DISP0_DAT8__GPIO_4_29, "SD POW"}, // disable    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(1, 8), MX6DL_PAD_GPIO_8__GPIO_1_8, "USB HUB POW"}, // disable    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(1, 4), MX6DL_PAD_GPIO_4__GPIO_1_4, "UPC POW"}, // disable    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(1, 2), MX6DL_PAD_GPIO_2__GPIO_1_2, "CAMERA POW"}, // disable    {gpio_dynamic, val_low, 0, "BOOTER", IMX_GPIO_NR(4, 24), MX6DL_PAD_DISP0_DAT3__GPIO_4_24, "TVP5158 POW"}, // disable    {0},};#endifstatic u32 crc32table[256];// make a crc32 tablestatic void i_make_table32(u32 aPoly) {    u32 nData, nAccum, i, j;    for ( i = 0; i < 256; ++i ) {        nData = i << 24, nAccum = 0;        for ( j = 0; j < 8; ++j ) {            if ( ( nData ^ nAccum ) & 0x80000000 )                nAccum = ( nAccum << 1 ) ^ aPoly;            else                nAccum <<= 1;            nData <<= 1;        }        crc32table[i] = nAccum;    }}// calculate crc32static u32 i_calculate_crc32(const u32 *aData, u32 aSize) {    u32 nAccum = 0, i;    static u32 init;    // 0x04C11DB7 is the standard    if ( !init ) i_make_table32(0x04C11DB7), ++init;    for ( i = 0; i < aSize; ++i ) {        u32 temp = *aData++;        nAccum = ( nAccum << 8 ) ^ crc32table[(( nAccum >> 24 ) ^ temp) & 0xff];        nAccum = ( nAccum << 8 ) ^ crc32table[(( nAccum >> 24 ) ^ (temp >> 8)) & 0xff];        nAccum = ( nAccum << 8 ) ^ crc32table[(( nAccum >> 24 ) ^ (temp >> 16)) & 0xff];        nAccum = ( nAccum << 8 ) ^ crc32table[( nAccum ^ temp) >> 24];    }    return nAccum;}#if !__LINUX_APPlong mxc_iomux_really_work(iomux_v3_cfg_t pad){    u32 mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;    u32 mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT;    u32 sel_input_ofs = (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT;    u32 sel_input = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;    u32 pad_ctrl_ofs = (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;    u32 pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;    void *base = (void *)IOMUXC_BASE_ADDR ;    if (mux_ctrl_ofs)        __raw_writel(mux_mode, base + mux_ctrl_ofs);    if (sel_input_ofs)        __raw_writel(sel_input, base + sel_input_ofs);    if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs)        __raw_writel(pad_ctrl, base + pad_ctrl_ofs);    return e_ok;}#else // linux applong mxc_iomux_really_work(iomux_v3_cfg_t pad){    return e_ok;}#endiflong mxc_iomux_v3_setup_pad(struct gpio_desc_body *desc, int permission){    long ret = e_ok;    if (!desc || (permission < per_user || permission > per_root)) {        printf("mxc_iomux_v3_setup_pad parameter error!\n");        ret = -e_invalid_parameters;        goto out;    }    switch (permission) {    case per_user:        if (desc->type != gpio_dynamic) {            printf("ERROR xxxxxxxxxxxxxxxxxx, user space can't "                   "pad gpio_init type io\n");            ret = -e_no_permission;            goto out;        }        break;    case per_kernel:        if (desc->type != gpio_dynamic) {            printf("ERROR xxxxxxxxxxxxxxxxx, in file  use \n");            ret = -e_no_permission;            goto out;        }        break;    case per_root:        {            static int is_first_time;            if (is_first_time == 0)                is_first_time++;            else {                printf("ERROR per_root permission not allowed!\n");                ret = -e_no_permission;                goto out;            }        }        break;    }    if (desc->if_pad_cfg == 0)        mxc_iomux_really_work(desc->pad_cfg);out:    return ret;}#if __BOOTER_CODElong write_gpio_table_to_ddr(void){    struct gpio_desc_skeleton *skep =        (struct gpio_desc_skeleton *)GPIO_TABLE_ADDR;    memset(skep, 0, GPIO_TABLE_MAP_SIZE);    skep->head_flag = 0x524c1234;    skep->version = 0x1;    skep->num = ARRAY_SIZE(desc_list);    memcpy(skep->body, desc_list, sizeof(desc_list));    skep->checksum =        i_calculate_crc32((u32 *)skep,        (sizeof(u32)*4 + sizeof(struct gpio_desc_body)*skep->num)>>2);    #if __debug__    printf("struct gpio_desc_skeleton size = %lu\n",        sizeof(struct gpio_desc_skeleton));    printf("struct gpio_desc_body size = %lu\n",        sizeof(struct gpio_desc_body));    printf("checksum = 0x%x\n", skep->checksum);    int i, j;    for (i=1; i<DESC_BODY_NUM; i++) {        for (j=0; j<sizeof(skep->body[i]); j++)            if (*((char *)&skep->body[i] + j) != 0)                printf("%d\n", i);    }    #endif    return e_ok;}long ywwh_gpio_init(void){    int permission = per_root;    int i;    for (i=0; i<ARRAY_SIZE(desc_list); i++) {        mxc_iomux_v3_setup_pad(&desc_list[i], permission);    }    return e_ok;}long ywwh_gpio_manage_func(void){    ywwh_gpio_init();    write_gpio_table_to_ddr();    return e_ok;}#else // kernel && app#if __LINUX_APPstatic long i_smmap_open(int *pfd, struct gpio_desc_skeleton **sm) {    printf("open!\n");    *pfd = open("/dev/mem", O_RDWR|O_SYNC); /* always exist, did not check */    printf("open1!\n");    *sm = mmap(NULL, GPIO_TABLE_MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, *pfd, GPIO_TABLE_ADDR);    printf("open2!\n");    if (*sm == MAP_FAILED) return -e_no_permission;    return e_ok;}static void i_smmap_close(int fd, struct gpio_desc_skeleton *sm) {    munmap(sm, GPIO_TABLE_MAP_SIZE);    close(fd);}#endifstatic struct gpio_desc_skeleton *descp;int mfd;long get_gpio_tbale_from_ddr(void) {    long ret = e_ok;    #if __LINUX_KERNEL    descp = ioremap(GPIO_TABLE_ADDR, _32K);    if (!descp)        ret = -e_unbelievable;    #else // linux app    if ((ret = i_smmap_open(&mfd, &descp)) < 0)        goto out;    #endifout:    return ret;}long is_gpio_table_valid(void){    if (descp->checksum == i_calculate_crc32((u32 *)descp,        (GPIO_TABLE_MAP_SIZE - 4) >> 2))        return 1;    else {        printf("headflag = 0x%x\n", descp->head_flag);        printf("num = %u\n", descp->num);        return 0;    }}long get_gpio_index_from_table(int gpio_nr, int *index){    long ret = e_ok;    int i;    if (!index) {        ret = -e_invalid_parameters;        goto out;    }    for (i=0; i<descp->num; i++) {        if (gpio_nr == descp->body[i].gpio_nr)            break;    }    if (i != descp->num)        *index = i;    else        ret = -e_object_not_exist;out:    return ret;}#endif//----------------------------------------------------------------------// -- test --#if __LINUX_APP#define IMX_GPIO_NR(bank, nr)       (((bank) - 1) * 32 + (nr))int main(){    long ret;    printf("struct gpio_desc_skeleton size = %lu\n",        sizeof(struct gpio_desc_skeleton));    printf("struct gpio_desc_body size = %lu\n",        sizeof(struct gpio_desc_body));    if ((ret = get_gpio_tbale_from_ddr()) < 0) {        printf("get_gpio_tbale_from_ddr failed: %ld!\n", ret);        return -1;    }    if (is_gpio_table_valid())        printf("crc ok!\n");    else {        printf("crc error!\n");        return -1;    }    printf("ok??\n");    int index;    if ((ret = get_gpio_index_from_table(IMX_GPIO_NR(4, 18), &index)) < 0) {        printf("get_gpio_index_from_table failed: %ld!\n", ret);        return -1;    }    printf("ok22??\n");    if ((ret = mxc_iomux_v3_setup_pad(&descp->body[index], per_root)) < 0) {        printf("mxc_iomux_v3_setup_pad failed: %ld!\n", ret);        return -1;    }    return 0;}#endif





0 0
原创粉丝点击