From: joanpau.beltran@uib.cat (Joan Pau Beltran)
To: kernelnewbies@lists.kernelnewbies.org
Subject: GPIO driver module for Jetway NF98 board
Date: Wed, 18 Jan 2012 22:40:34 +0100 [thread overview]
Message-ID: <4F173C52.5010805@uib.cat> (raw)
In-Reply-To: <4F17302B.3050402@uib.cat>
Sorry for the noise, but the last code was from a primitive version with
several typos and errors. Sorry for the noise.
Here it goes the fixed code:
#include <linux/module.h>
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/gpio.h>
#include <asm-generic/io.h>
/* TODO: Look how to get the GPIO base address from the LPC interface.*/
#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;
uint8_t 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);
return 0;
}
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;
uint8_t 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);
}
return 0;
}
static int jwnf98_gpio_get(struct gpio_chip *gc, unsigned off)
{
unsigned long add;
unsigned bit;
uint8_t byte;
if (off)
{
add = PINX_STATUS;
bit = off;
}
else
{
add = PIN0_STATUS;
bit = PIN0_BIT;
}
byte = inb(add);
byte &= (1 << bit);
return !!byte; /* Is the double negation !! needed? */
}
static void jwnf98_gpio_set(struct gpio_chip *gc, unsigned off, int val)
{
unsigned long add;
unsigned bit;
uint8_t 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 jwnf98_gpio_chip = {
.label = "jwnf98_gpio",
.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 = NULL,
.can_sleep = 0,
};
static int __init jwnf98_gpio_init(void)
{
/*
Do preliminar work here:
- Request ports? DONE.
- Create the chip here instead of let it be static? How? NOT
NEEDED.
- Enable gpio function for each pin? DONE.
- Something else?
*/
uint8_t byte;
request_region(PIN0_FUNCTION, 1, "jwnf98_gpio");
request_region(PIN0_DIRECTION, 1, "jwnf98_gpio");
request_region(PIN0_STATUS, 1, "jwnf98_gpio");
request_region(PIN0_BIT, 1, "jwnf98_gpio");
request_region(PINX_FUNCTION, 1, "jwnf98_gpio");
request_region(PINX_DIRECTION, 1, "jwnf98_gpio");
request_region(PINX_STATUS, 1, "jwnf98_gpio");
/*
Should we check that the requested memory is available? How?
*/
byte = inb(PIN0_FUNCTION);
byte |= (1 << PIN0_BIT);
outb(byte, PIN0_FUNCTION);
byte = inb(PINX_FUNCTION);
byte |= ~1;
outb(byte, PINX_FUNCTION);
/*
Should we add the gpio_chip here with gpiochip_add?
*/
return gpiochip_add(&jwnf98_gpio_chip);
}
static void __exit jwnf98_gpio_exit(void)
{
/*
Do cleanup work here:
- Release ports? DONE.
- Delete the chip if it was created on init function
instead of being static? How? NOT NEEDED.
- Disable gpio function for each pin? DONE.
- Something else?
*/
uint8_t byte;
byte = inb(PIN0_FUNCTION);
byte &= ~(1 << PIN0_BIT);
outb(byte, PIN0_FUNCTION);
byte = inb(PINX_FUNCTION);
byte &= 1;
outb(byte, PIN0_FUNCTION);
release_region(PIN0_FUNCTION, 1);
release_region(PIN0_DIRECTION, 1);
release_region(PIN0_STATUS, 1);
release_region(PIN0_BIT, 1);
release_region(PINX_FUNCTION, 1);
release_region(PINX_DIRECTION, 1);
release_region(PINX_STATUS, 1);
/*
Should we remove the gpio_chip here? How to do that?
*/
}
module_init(jwnf98_gpio_init);
module_exit(jwnf98_gpio_exit);
MODULE_DESCRIPTION("Jetway NF98 GPIO driver");
MODULE_LICENSE("GPL");
--
Joan Pau Beltran
next prev parent reply other threads:[~2012-01-18 21:40 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-21 17:34 GPIO driver module for Jetway NF98 board Joan Pau Beltran
2011-12-22 1:21 ` Josh Cartwright
[not found] ` <20111222001549.GA14353@joshcartwright.net>
2011-12-28 17:03 ` Joan Pau Beltran
2011-12-29 17:53 ` Josh Cartwright
2012-01-18 20:48 ` Joan Pau Beltran
2012-01-18 21:40 ` Joan Pau Beltran [this message]
2012-01-23 21:00 ` Joan Pau Beltran
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F173C52.5010805@uib.cat \
--to=joanpau.beltran@uib.cat \
--cc=kernelnewbies@lists.kernelnewbies.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.