GPIO driver module for Jetway NF98 board

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi everyone,

I did not find any existing driver for the GPIO port of the Jetway NF98 mini-itx board, so I would like to write a module for that, using the gpiolib interface.

Since the board documentation does not include any information about the GPIOs, I contacted the Jetway support team. However, the only answer was the attached code for Windows (NF98GPIO.c).
As you can see, it seems clear how to set the pin states for output, but not how to read them in input mode. I asked again and the response was (literally):
input sample code:
{
data= "">
}
//final exit SIO
outp(INDEX_PORT,0xaa);
return data;
It makes no sense, and it is very upsetting.
I would try to read from the same address used for output, but this is just an idea to be tested.

Since I have not written any kernel module before, after reading the pertinent documentation about memory management, i/o port access, and gpiolib, I have some questions.

1. How should I request/release the ports mentioned in the attached file? Should I use the request_region/release_region functions from linux/ioport.h? In such case, what should I do with the returned struct resource?

2. I suppose that I should use the same addresses given by the support team, although their code is for windows. Is it ok?

3. Should/could I use the test_bit, set_bit, clear_bit functions to get, set the bit in the needed read/write functions I am writing? Or should I use the sequence 'inb - mask the value properly - outb' ?


The second file attached is an skeleton of the module I am trying to write, any comments or suggestions are welcome.

Thanks in advance!
-- 
Joan Pau Beltran
#include <linux/module.h>
#include <linux/types.h>
#include <asm-generic/io.h>

#define GPIO_BASE 0x500;

// pin 0 (GPIO 21) is controlled by an specific bit of a different set of ports:
#define PIN0_FUNCTION  GPIO_BASE + 0x2;
#define PIN0_DIRECTION GPIO_BASE + 0x6;
#define PIN0_STATUS    GPIO_BASE + 0xE;
#define PIN0_BIT       5;

  // pins 1 to 7 (GPIO 33 to 39) correspond to the respective bit on these ports
#define PINX_FUNCTION  GPIO_BASE + 0x30;
#define PINX_DIRECTION GPIO_BASE + 0x34;
#define PINX_STATUS    GPIO_BASE + 0x38;


static int jwnf98_gpio_direction_input(struct gpio_chip *gc, unsigned off)
{
	unsigned long dir_add;
	unsigned bit_off;
	u8 byte;
	if (off)
	{
		dir_add = PINX_DIRECTION;
		bit_off = off;
	}
	else
	{
		dir_add = PIN0_DIRECTION;
		bit_off = PIN0_BIT;
	}
	byte = inb(dir_add);
	byte |= (1 << bit_off);
	outb(byte, dir_add);
}

static int jwnf98_gpio_direction_output(struct gpio_chip *gc, unsigned off, int val)
{
	unsigned long dir_add;
	unsigned long val_add;
	unsigned bit_off;
	u8 byte;
	if (off)
	{
		dir_add = PINX_DIRECTION;
		val_add = PINX_STATUS;
		bit_off = off;
	}
	else
	{
		dir_add = PIN0_DIRECTION;
		val_add = PIN0_STATUS;
		bit_off = PIN0_BIT;
	}
	byte = inb(dir_add);
	byte &= ~(1 << bit_off);
	outb(byte, dir_add);
	if (val)
	{
		byte = inb(val_add);
		byte |= (1 << bit_off);
		outb(byte, val_add);
	}
	else
	{
		byte = inb(val_add);
		byte |= (1 << bit_off);
		outb(byte, val_add);
	}
}

static int jwnf98_gpio_get(struct gpio_chip *gc, unsigned off)
{
/* 
  Nothing here, waiting for support team answer.
  Maybe read from the same address than output?
*/
}

static void jwnf98_gpio_set(struct gpio_chip *gc, unsigned off, int val)
{
	unsigned long add;
	unsigned bit;
	u8 byte;
	if (off)
	{
		add = PINX_STATUS;
		bit = off;
	}
	else
	{
		add = PIN0_STATUS;
		bit = PIN0_BIT;
	}
	byte = inb(add);
	if (val)
		byte |= (1 << bit);
	else
		byte &= ~(1 << bit);
	outb(byte, add);
}

static struct gpio_chip gpio_pins = {
	.label = "jwnf98",
	.owner = THIS_MODULE,
	.direction_input  = jwnf98_gpio_direction_input,
	.get = jwnf98_gpio_get,
	.direction_output = jwnf98_gpio_direction_output,
	.set = jwnf98_gpio_set,
	.dbg_show = jwnf98_gpio_dbg_show,
	.can_sleep = 0,
};

static int __init jwnf98_gpio_init(void)
{
	/* 
	Do preliminar work here:
		- Request ports?
		- Create the chip here instead of let it be static? How?
		- Something else?
	*/
}

static void __exit jwnf98_gpio_exit(void)
{
	/* 
	Do cleanup work here:
		- Release ports?
		- Delete the chip if it was created on init function 
		  instead of being static? How?
		- Something else?
	*/
}

module_init(jwnf98_gpio_init);
module_exit(jwnf98_gpio_exit);

MODULE_DESCRIPTION("Jetway NF98 GPIO driver");
MODULE_LICENSE("GPL");
/*                 GPIO_CON
  								  _ _ _ 
GPIO21 >>----------|1	  2|----------<<GPIO36
GPIO33 >>----------|3		4|----------<<GPIO37
GPIO34 >>----------|5   6|----------<<GPIO38
GPIO35 >>----------|7		8|----------<<GPIO39
							-----|9	 10|----------OVCC
							|		  - - -			|	
							
GPIO21 GPIO_Base + offset_2_bit_5 Set 1 For Gpio Funtion
       GPIO_Base + offset_6_bit_5 Set 0/1 For Output/input	
       GPIO_Base + offset_E_bit_5 Set 0/1 For Low/High Only in Output Mode
       
GPIO32+n GPIO_Base + offset_30_bit_(1+n) Set 1 For Gpio Function      
       	 GPIO_Base + offset_34_bit_(1+n) Set 0/1 For Output/input	
      	 GPIO_Base + offset_38_bit_(1+n) Set 0/1 For Low/High Only in Output Mode		
parameter first
1-8
parameter second
0 ->output
1 ->input
parameter third
0 ->low
1 ->high
for NF98 GPIO				 
*/
#include <conio.h>
#include <stdio.h>
#include <dos.h>
int offset=0x30,Val_offset=0x8;
int inout;//second
int highlow;//three
int GPIO_Base=0x500;
int bit=0;
int status;

int main(int argc,char* argv[]){
	printf("-------------------------This Program only for NF98 GPIO Function\n-------------------------Don't Run At Others MainBoard!!!!!\n");
  if(argc <3)
  	{
  		printf("Error!\nUsage:NF98GPIO Pin_num Out/in_put High/low(Only Output mode)");
  		return 0;
  		}
  sscanf(argv[1],"%d",&bit);	
  sscanf(argv[2],"%d",&inout);	
  inout=inout&1;
  if(argc>=4)
  sscanf(argv[3],"%d",&highlow);	
  highlow=highlow&1;

  switch(bit)
  {
	case 1:offset=0x2; bit=5;Val_offset=0x0C;break;
	case 2:bit=4;break;
	case 3:bit=1;break;
	case 4:bit=5;break;
	case 5:bit=2;break;
	case 6:bit=6;break;
	case 7:bit=3;break;
	case 8:bit=7;break;
	default:printf("You must input correct NUM (1-8)!\n");
	return 0;
  }

	//setp 1.set gpio Function
	status=(int)inp(GPIO_Base+offset);
	outp(GPIO_Base+offset, (1<<bit)|status);//set bit to 1

	//step 2.set gpio mode
	status=(int)inp(GPIO_Base+offset+4);
	outp(GPIO_Base+offset+4,status&(~(1<<bit))|(inout<<bit));
  
  //setp 3.set gpio High / Low only for Output mode
  if(argc >=4)
  {
	status=(int)inp(GPIO_Base+offset+Val_offset);
	outp(GPIO_Base+offset+Val_offset,status&(~(1<<bit))|(highlow<<bit));	
	}
	
	return 1;
}
_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux