OSDN Git Service

V4L/DVB (11885): Siano: Add new GPIO management interface
authorUri Shkolnik <uris@siano-ms.com>
Tue, 19 May 2009 14:49:19 +0000 (11:49 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 16 Jun 2009 22:14:38 +0000 (19:14 -0300)
Add new GPIO management interface to replace old (buggy) one.
Keeping old interface intact for now.

Signed-off-by: Uri Shkolnik <uris@siano-ms.com>
Acked-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb/siano/sms-cards.c
drivers/media/dvb/siano/smscoreapi.c
drivers/media/dvb/siano/smscoreapi.h

index 1a18906..370cf51 100644 (file)
@@ -109,7 +109,7 @@ static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
 {
        int lvl, ret;
        u32 gpio;
-       struct smscore_gpio_config gpioconfig = {
+       struct smscore_config_gpio gpioconfig = {
                .direction            = SMS_GPIO_DIRECTION_OUTPUT,
                .pullupdown           = SMS_GPIO_PULLUPDOWN_NONE,
                .inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
index 00a1053..043368a 100644 (file)
@@ -1276,8 +1276,9 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 EXPORT_SYMBOL_GPL(smsclient_sendrequest);
 
 
+/* old GPIO managments implementation */
 int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
-                          struct smscore_gpio_config *pinconfig)
+                          struct smscore_config_gpio *pinconfig)
 {
        struct {
                struct SmsMsgHdr_ST hdr;
@@ -1346,6 +1347,238 @@ int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
                                            &msg, sizeof(msg));
 }
 
+/* new GPIO managment implementation */
+static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
+               u32 *pGroupNum, u32 *pGroupCfg) {
+
+       *pGroupCfg = 1;
+
+       if (PinNum >= 0 && PinNum <= 1) {
+               *pTranslatedPinNum = 0;
+               *pGroupNum = 9;
+               *pGroupCfg = 2;
+       } else if (PinNum >= 2 && PinNum <= 6) {
+               *pTranslatedPinNum = 2;
+               *pGroupNum = 0;
+               *pGroupCfg = 2;
+       } else if (PinNum >= 7 && PinNum <= 11) {
+               *pTranslatedPinNum = 7;
+               *pGroupNum = 1;
+       } else if (PinNum >= 12 && PinNum <= 15) {
+               *pTranslatedPinNum = 12;
+               *pGroupNum = 2;
+               *pGroupCfg = 3;
+       } else if (PinNum == 16) {
+               *pTranslatedPinNum = 16;
+               *pGroupNum = 23;
+       } else if (PinNum >= 17 && PinNum <= 24) {
+               *pTranslatedPinNum = 17;
+               *pGroupNum = 3;
+       } else if (PinNum == 25) {
+               *pTranslatedPinNum = 25;
+               *pGroupNum = 6;
+       } else if (PinNum >= 26 && PinNum <= 28) {
+               *pTranslatedPinNum = 26;
+               *pGroupNum = 4;
+       } else if (PinNum == 29) {
+               *pTranslatedPinNum = 29;
+               *pGroupNum = 5;
+               *pGroupCfg = 2;
+       } else if (PinNum == 30) {
+               *pTranslatedPinNum = 30;
+               *pGroupNum = 8;
+       } else if (PinNum == 31) {
+               *pTranslatedPinNum = 31;
+               *pGroupNum = 17;
+       } else
+               return -1;
+
+       *pGroupCfg <<= 24;
+
+       return 0;
+}
+
+int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+               struct smscore_gpio_config *pGpioConfig) {
+
+       u32 totalLen;
+       u32 TranslatedPinNum;
+       u32 GroupNum;
+       u32 ElectricChar;
+       u32 groupCfg;
+       void *buffer;
+       int rc;
+
+       struct SetGpioMsg {
+               struct SmsMsgHdr_ST xMsgHeader;
+               u32 msgData[6];
+       } *pMsg;
+
+
+       if (PinNum > MAX_GPIO_PIN_NUMBER)
+               return -EINVAL;
+
+       if (pGpioConfig == NULL)
+               return -EINVAL;
+
+       totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
+
+       buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+                       GFP_KERNEL | GFP_DMA);
+       if (!buffer)
+               return -ENOMEM;
+
+       pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+       pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+       pMsg->xMsgHeader.msgDstId = HIF_TASK;
+       pMsg->xMsgHeader.msgFlags = 0;
+       pMsg->xMsgHeader.msgLength = (u16) totalLen;
+       pMsg->msgData[0] = PinNum;
+
+       if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
+               pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
+               if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
+                               &groupCfg) != 0)
+                       return -EINVAL;
+
+               pMsg->msgData[1] = TranslatedPinNum;
+               pMsg->msgData[2] = GroupNum;
+               ElectricChar = (pGpioConfig->PullUpDown)
+                               | (pGpioConfig->InputCharacteristics << 2)
+                               | (pGpioConfig->OutputSlewRate << 3)
+                               | (pGpioConfig->OutputDriving << 4);
+               pMsg->msgData[3] = ElectricChar;
+               pMsg->msgData[4] = pGpioConfig->Direction;
+               pMsg->msgData[5] = groupCfg;
+       } else {
+               pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
+               pMsg->msgData[1] = pGpioConfig->PullUpDown;
+               pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
+               pMsg->msgData[3] = pGpioConfig->OutputDriving;
+               pMsg->msgData[4] = pGpioConfig->Direction;
+               pMsg->msgData[5] = 0;
+       }
+
+       smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+       rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+                       &coredev->gpio_configuration_done);
+
+       if (rc != 0) {
+               if (rc == -ETIME)
+                       sms_err("smscore_gpio_configure timeout");
+               else
+                       sms_err("smscore_gpio_configure error");
+       }
+       kfree(buffer);
+
+       return rc;
+}
+
+int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+               u8 NewLevel) {
+
+       u32 totalLen;
+       int rc;
+       void *buffer;
+
+       struct SetGpioMsg {
+               struct SmsMsgHdr_ST xMsgHeader;
+               u32 msgData[3]; /* keep it 3 ! */
+       } *pMsg;
+
+       if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER) ||
+                       (PinNum > MAX_GPIO_PIN_NUMBER))
+               return -EINVAL;
+
+       totalLen = sizeof(struct SmsMsgHdr_ST) +
+                       (3 * sizeof(u32)); /* keep it 3 ! */
+
+       buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+                       GFP_KERNEL | GFP_DMA);
+       if (!buffer)
+               return -ENOMEM;
+
+       pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+       pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+       pMsg->xMsgHeader.msgDstId = HIF_TASK;
+       pMsg->xMsgHeader.msgFlags = 0;
+       pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
+       pMsg->xMsgHeader.msgLength = (u16) totalLen;
+       pMsg->msgData[0] = PinNum;
+       pMsg->msgData[1] = NewLevel;
+
+       /* Send message to SMS */
+       smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+       rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+                       &coredev->gpio_set_level_done);
+
+       if (rc != 0) {
+               if (rc == -ETIME)
+                       sms_err("smscore_gpio_set_level timeout");
+               else
+                       sms_err("smscore_gpio_set_level error");
+       }
+       kfree(buffer);
+
+       return rc;
+}
+
+int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+               u8 *level) {
+
+       u32 totalLen;
+       int rc;
+       void *buffer;
+
+       struct SetGpioMsg {
+               struct SmsMsgHdr_ST xMsgHeader;
+               u32 msgData[2];
+       } *pMsg;
+
+
+       if (PinNum > MAX_GPIO_PIN_NUMBER)
+               return -EINVAL;
+
+       totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
+
+       buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+                       GFP_KERNEL | GFP_DMA);
+       if (!buffer)
+               return -ENOMEM;
+
+       pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+       pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+       pMsg->xMsgHeader.msgDstId = HIF_TASK;
+       pMsg->xMsgHeader.msgFlags = 0;
+       pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
+       pMsg->xMsgHeader.msgLength = (u16) totalLen;
+       pMsg->msgData[0] = PinNum;
+       pMsg->msgData[1] = 0;
+
+       /* Send message to SMS */
+       smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+       rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+                       &coredev->gpio_get_level_done);
+
+       if (rc != 0) {
+               if (rc == -ETIME)
+                       sms_err("smscore_gpio_get_level timeout");
+               else
+                       sms_err("smscore_gpio_get_level error");
+       }
+       kfree(buffer);
+
+       /* Its a race between other gpio_get_level() and the copy of the single
+        * global 'coredev->gpio_get_res' to  the function's variable 'level'
+        */
+       *level = coredev->gpio_get_res;
+
+       return rc;
+}
+
 static int __init smscore_module_init(void)
 {
        int rc = 0;
index 6e23c5f..03bdc94 100644 (file)
@@ -549,7 +549,7 @@ struct SMSHOSTLIB_I2C_RES_ST {
 };
 
 
-struct smscore_gpio_config {
+struct smscore_config_gpio {
 #define SMS_GPIO_DIRECTION_INPUT  0
 #define SMS_GPIO_DIRECTION_OUTPUT 1
        u8 direction;
@@ -575,6 +575,48 @@ struct smscore_gpio_config {
        u8 outputdriving;
 };
 
+struct smscore_gpio_config {
+#define SMS_GPIO_DIRECTION_INPUT  0
+#define SMS_GPIO_DIRECTION_OUTPUT 1
+       u8 Direction;
+
+#define SMS_GPIO_PULLUPDOWN_NONE     0
+#define SMS_GPIO_PULLUPDOWN_PULLDOWN 1
+#define SMS_GPIO_PULLUPDOWN_PULLUP   2
+#define SMS_GPIO_PULLUPDOWN_KEEPER   3
+       u8 PullUpDown;
+
+#define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL  0
+#define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1
+       u8 InputCharacteristics;
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW         1 /* 10xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST         0 /* 10xx */
+
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS    0 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS     1 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS     2 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS     3 /* 11xx */
+       u8 OutputSlewRate;
+
+#define SMS_GPIO_OUTPUT_DRIVING_S_4mA          0 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_8mA          1 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_12mA         2 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_16mA         3 /* 10xx */
+
+#define SMS_GPIO_OUTPUT_DRIVING_1_5mA          0 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_2_8mA          1 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_4mA                    2 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_7mA                    3 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_10mA                   4 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_11mA                   5 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_14mA                   6 /* 11xx */
+#undef SMS_GPIO_OUTPUT_DRIVING_16mA
+#define SMS_GPIO_OUTPUT_DRIVING_16mA                   7 /* 11xx */
+       u8 OutputDriving;
+};
+
 extern void smscore_registry_setmode(char *devpath, int mode);
 extern int smscore_registry_getmode(char *devpath);
 
@@ -616,10 +658,19 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev);
 extern void smscore_putbuffer(struct smscore_device_t *coredev,
                              struct smscore_buffer_t *cb);
 
+/* old GPIO managment */
 int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
-                          struct smscore_gpio_config *pinconfig);
+                          struct smscore_config_gpio *pinconfig);
 int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
 
+/* new GPIO managment */
+extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+               struct smscore_gpio_config *pGpioConfig);
+extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+               u8 NewLevel);
+extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+               u8 *level);
+
 void smscore_set_board_id(struct smscore_device_t *core, int id);
 int smscore_get_board_id(struct smscore_device_t *core);