From: Glen Wernersbach <glen@domain.hid>
To: Philippe Gerum <rpm@xenomai.org>
Cc: "xenomai@xenomai.org" <xenomai@xenomai.org>
Subject: Re: [Xenomai-help] Linux Serial Does not work with CONFIG_XENO_OPT_PERVASIVE enabled
Date: Wed, 21 Mar 2012 10:41:28 -0400 [thread overview]
Message-ID: <CB8F60DA.1EE9B%glen@domain.hid> (raw)
In-Reply-To: <4F699381.30105@domain.hid>
[-- Attachment #1: Type: text/plain, Size: 2318 bytes --]
Hi guys,
One thing about both of these drivers is they have been modified to set some
GPIO pins.
The come down to the pca9539_gpio_set_value() in this file.
Do you see any reason why those would not take under Xenomai?
Glen
On 3/21/12 4:38 AM, "Philippe Gerum" <rpm@xenomai.org> wrote:
> On 03/21/2012 05:46 AM, Glen Wernersbach wrote:
>> I am going to start trying to see if I can figure out what is not getting
>> set.
>>
>
> You could get useful information from the pipeline tracer, by enabling
> CONFIG_IPIPE_TRACE, observing what exactly happens in kernel space from
> the issuing of the ioctl() syscall until the the read() syscall on the
> serial link.
>
> You could set markers using Xenomai's I-pipe trace API in userland to
> highlight portions of interest in your app code, freezing the capture to
> snapshot a particular moment in the execution timeline. See
> http://xenomai.org/index.php/I-pipe:Tracer.
>
> NOTE: pay attention to the value in /proc/ipipe/trace/back_trace_points
> to hold enough data.
>
>> By the way. This board also has 4 other serial ports on a 8250.c driver. It
>> also fails under the xeno build.
>>
>>
>>
>>
>> On 3/20/12 4:35 PM, "Gilles Chanteperdrix"
>> <gilles.chanteperdrix@xenomai.org> wrote:
>>
>>> On 03/20/2012 09:19 PM, Glen Wernersbach wrote:
>>>> I actually think in is in the settings because if run just the setup part
>>>> of
>>>> the code without reading and writing, on the kernel that works my activity
>>>> LED turns off.
>>>>
>>>> On the xeno kernel the LED never changes.
>>>
>>> I actually think that CONFIG_XENO_OPT_PERVASIVE does not make any
>>> difference which could cause a difference of hardware behaviour. So, it
>>> must be another option triggered by this config change. So, if you want
>>> us to help you, please post the .configs.
>>>
>>
>
--
Glen Wernersbach
President & CTO
Jetsoft Development Co.
629 Old St Rt. 74 Suite 210
Cincinnati, Oh 45244
Custom Programming Web Site: www.jetsoftdev.com
Retail Products Web Site: www.scanhelp.com
Phone: 513-528-6660
Fax: 513-528-3470
Cell 513-240-9929
----
Partner for Software Technology
Jacobs Automation
2365 Progress Drive
Hebron, KY 41048
(513) 297-7550
----
"Support Dyslexia Research"
[-- Attachment #2: pca9555_gpio.c --]
[-- Type: application/octet-stream, Size: 12088 bytes --]
/*
* GPIO driver for Artila M502 based on Atmel AT91SAM9G20 (Thunder)
*
* Copyright (C) 2010 Artila Electronics,Ltd
*
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <mach/hardware.h>
#include <mach/at91_pio.h>
#include <mach/gpio.h>
#include <linux/i2c.h>
#include <asm/pca9539.h>
#define GPIO_MINOR 254
#define PIN 0
#define OUTP 1
#define INP 2
#define LOW 0
#define HIGH 1
/* IOCTL Commands */
#define GPIO_IOCTL_COUNT 0
#define GPIO_IOCTL_DIPSW 1
#define GPIO_IOCTL_GET 2
#define GPIO_IOCTL_SET 3
#define GPIO_IOCTL_CLEAR 4
#define GPIO_IOCTL_OUTPUT 5
#define GPIO_IOCTL_INPUT 6
#define GPIO_IOCTL_MODE 7
#define GPIO_IOCTL_INPUT_SET 8
#define GPIO_IOCTL_STATUS 0xa001
//static DEFINE_SPINLOCK(gpio_lock);
int chips = 0;
int init_error = 0;
#ifdef CONFIG_MACH_M502
#define M504_GPIO_COUNT 24
#define M504_GPIO_SW 2
static int M502_GPIO[M504_GPIO_COUNT+M504_GPIO_SW] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
AT91_PIN_PC15,
16,17,
AT91_PIN_PC1,
18,19,20,21,22,
AT91_PIN_PB12,
AT91_PIN_PB13,
};
static int M502_MODE[M504_GPIO_COUNT+M504_GPIO_SW];
#elif defined(CONFIG_MACH_PAC4010)
#define M504_GPIO_COUNT 16
#define M504_GPIO_SW 0
static int M502_GPIO[M504_GPIO_COUNT+M504_GPIO_SW] = {
0,1, 2, 3, 4, 5, 6, 7,
8,9,10,11,12,13,14,16,
};
static int M502_MODE[M504_GPIO_COUNT+M504_GPIO_SW];
#else
#define M504_GPIO_COUNT 21
#define M504_GPIO_SW 0
static int M502_GPIO[M504_GPIO_COUNT+M504_GPIO_SW] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14, // 15
21,
16,17,
22,
19,20
};
static int M502_MODE[M504_GPIO_COUNT+M504_GPIO_SW];
#endif
#define M504_TOTAL_GPIO (M504_GPIO_COUNT+M504_GPIO_SW)
/* ......................................................................... */
#define PCA953X_INPUT 0
#define PCA953X_OUTPUT 1
#define PCA953X_INVERT 2
#define PCA953X_DIRECTION 3
static const struct i2c_device_id pca9539_id[] = {
{ "pca9539", 16, },
{ }
};
MODULE_DEVICE_TABLE(i2c, pca9539_id);
struct pca9539_chip {
unsigned gpio_start;
uint16_t reg_output;
uint16_t reg_direction;
struct i2c_client *client;
};
struct pca9539_chip *save_chip[2];
static int pca9539_write_reg(struct pca9539_chip *chip, int reg, uint16_t val)
{
int ret;
ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);
if (ret < 0) {
dev_err(&chip->client->dev, "failed writing register\n");
return ret;
}
return 0;
}
static int pca9539_read_reg(struct pca9539_chip *chip, int reg, uint16_t *val)
{
int ret;
ret = i2c_smbus_read_word_data(chip->client, reg << 1);
if (ret < 0) {
dev_err(&chip->client->dev, "failed reading register\n");
return ret;
}
*val = (uint16_t)ret;
return 0;
}
static int pca9539_gpio_direction_input(unsigned off)
{
struct pca9539_chip *chip;
uint16_t reg_val;
int ret;
int save = off;
if(M502_GPIO[save] >= 0 && M502_GPIO[save] <= 32) {
off = M502_GPIO[save];
chip = save_chip[off< 16 ? 0 : 1];
if(off >= 16)
off = off -16;
reg_val = chip->reg_direction | (1u << off);
ret = pca9539_write_reg(chip, PCA953X_DIRECTION, reg_val);
if (ret)
return ret;
chip->reg_direction = reg_val;
}else
at91_set_gpio_input(M502_GPIO[save], 0);
M502_MODE[save] = 1;
return 0;
}
int pca9539_gpio_direction_output(unsigned off, int val, int flag)
{
struct pca9539_chip *chip;
uint16_t reg_val;
int ret;
int save = off;
if(flag == 1) {
if(off < M504_TOTAL_GPIO)
{
if(M502_GPIO[save] >= 0 && M502_GPIO[save] <= 32)
{
off = M502_GPIO[save];
}
}
}
if((off >= 0 && off <= 32 && M502_GPIO[save] >= 0 && M502_GPIO[save] <= 32)) {
chip = save_chip[off < 16 ? 0 : 1];
if(off >= 16)
off = off -16;
/* set output level */
if (val)
reg_val = chip->reg_output | (1u << off);
else
reg_val = chip->reg_output & ~(1u << off);
ret = pca9539_write_reg(chip, PCA953X_OUTPUT, reg_val);
if (ret)
return ret;
chip->reg_output = reg_val;
/* then direction */
reg_val = chip->reg_direction & ~(1u << off);
ret = pca9539_write_reg(chip, PCA953X_DIRECTION, reg_val);
if (ret)
return ret;
chip->reg_direction = reg_val;
}else {
if(flag)
at91_set_gpio_output(M502_GPIO[save], 0);
}
M502_MODE[save] = 0;
return 0;
}
EXPORT_SYMBOL(pca9539_gpio_direction_output);
static int pca9539_gpio_get_value(unsigned off)
{
struct pca9539_chip *chip;
uint16_t reg_val;
int ret;
int save = off;
if(M502_GPIO[save] >= 0 && M502_GPIO[save] <= 32) {
off = M502_GPIO[save];
chip = save_chip[off < 16 ? 0 : 1];
if(off >= 16)
off = off -16;
ret = pca9539_read_reg(chip, PCA953X_INPUT, ®_val);
if (ret < 0) {
/* NOTE: diagnostic already emitted; that's all we should
* do unless gpio_*_value_cansleep() calls become different
* from their nonsleeping siblings (and report faults).
*/
return 0;
}
return (reg_val & (1u << off)) ? 1 : 0;
}
return at91_get_gpio_value(M502_GPIO[off]);
}
void pca9539_gpio_set_value(unsigned off, int val , int flag)
{
struct pca9539_chip *chip;
uint16_t reg_val;
int ret;
int save = off;
if(flag == 1) {
if(off < M504_TOTAL_GPIO)
{
if(M502_GPIO[save] >= 0 && M502_GPIO[save] <= 32) {
off = M502_GPIO[save];
}
}
}
if(off >= 0 && off <= 32 && M502_GPIO[save] >= 0 && M502_GPIO[save] <= 32) {
chip = save_chip[off < 16 ? 0 : 1];
if(off >= 16)
off = off -16;
if (val)
reg_val = chip->reg_output | (1u << off);
else
reg_val = chip->reg_output & ~(1u << off);
ret = pca9539_write_reg(chip, PCA953X_OUTPUT, reg_val);
if (ret)
return;
chip->reg_output = reg_val;
}else{
if(flag)
at91_set_gpio_output(M502_GPIO[save], val);
}
}
EXPORT_SYMBOL(pca9539_gpio_set_value);
/*
* GPIO device is opened, and GPIO starts running.
*/
static int m502_gpio_open(struct inode *inode, struct file *file)
{
//spin_lock(&gpio_lock);
//gpio_open_cnt++;
//spin_unlock(&gpio_lock);
return 0;
}
/*
* Close the GPIO device.
* If CONFIG_GPIO_NOWAYOUT is NOT defined then the GPIO is also
* disabled.
*/
static int m502_gpio_close(struct inode *inode, struct file *file)
{
//spin_lock(&gpio_lock);
//spin_unlock(&gpio_lock);
return 0;
}
/*
* Handle commands from user-space.
*/
static int m502_gpio_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
int i = *((int __user *) argp);
switch(cmd){
case GPIO_IOCTL_COUNT:
*((int __user *) argp) = M504_GPIO_COUNT;
return 0;
case GPIO_IOCTL_DIPSW:
*((int __user *) argp) = M504_GPIO_SW;
return 0;
case GPIO_IOCTL_GET:
i = *((int __user *) argp);
if(i >= M504_TOTAL_GPIO)
return -EINVAL;
if(M504_GPIO_COUNT > i)
return pca9539_gpio_get_value(i);
else {
return at91_get_gpio_value(M502_GPIO[i]);
}
case GPIO_IOCTL_SET:
i = *((int __user *) argp);
if(i >= M504_GPIO_COUNT )
return -EINVAL;
if(M502_MODE[i] == 1)
return -EINVAL;
else
pca9539_gpio_set_value(*((int __user *) argp),1,1);
return 0;
case GPIO_IOCTL_CLEAR:
i = *((int __user *) argp);
if(i >= M504_GPIO_COUNT )
return -EINVAL;
if(M502_MODE[i] == 1)
return -EINVAL;
else
pca9539_gpio_set_value(*((int __user *) argp),0,1);
return 0;
case GPIO_IOCTL_OUTPUT:
#if defined(CONFIG_MACH_PAC4010)
return 1;
#endif
i = *((int __user *) argp);
if(i >= M504_GPIO_COUNT )
return -EINVAL;
pca9539_gpio_direction_output(i,0,1);
return 0;
case GPIO_IOCTL_INPUT:
#if defined(CONFIG_MACH_PAC4010)
return 1;
#endif
i = *((int __user *) argp);
//printk("%d\n",i);
if(i >= M504_GPIO_COUNT)
return -EINVAL;
pca9539_gpio_direction_input(i);
return 0;
case GPIO_IOCTL_MODE:
i = *((int __user *) argp);
if(i >= M504_TOTAL_GPIO)
return -EINVAL;
if(M504_GPIO_COUNT > i)
return M502_MODE[i];
else
return 1;
/*case GPIO_IOCTL_INPUT_SET:
i = *((int __user *) argp);
return at91_set_gpio_input(M504_GPIO_MAP[i][0], 1);
*/
/*case 0xa001:
for (i = M504_TOTAL_GPIO ; i >= 0 ; i--) {
status <<= 1;
if(at91_get_gpio_value(M504_GPIO_MAP[i]))
status++;
}
*((unsigned long __user *) argp) = status;
return 0;*/
default:return -ENOIOCTLCMD;
}
return -ENOIOCTLCMD;
}
/* ......................................................................... */
static struct file_operations m502gpio_fops =
{
.owner = THIS_MODULE,
.ioctl = m502_gpio_ioctl,
.open = m502_gpio_open,
.release = m502_gpio_close,
//.read = matrix500_gpio_read,
//.write = matrix500_gpio_write,
};
static struct miscdevice m502_gpio_miscdev =
{
.minor = GPIO_MINOR,
.name = "gpio",
.fops = &m502gpio_fops,
};
static int __devinit pca9539_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
| I2C_FUNC_SMBUS_BYTE_DATA|
I2C_FUNC_SMBUS_WORD_DATA)) {
ret = -ENODEV;
return -EINVAL;
}
save_chip[chips] = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL);
if (save_chip[chips] == NULL)
return -ENOMEM;
save_chip[chips]->client = client;
save_chip[chips]->gpio_start = id->driver_data;
ret = pca9539_read_reg(save_chip[chips], PCA953X_OUTPUT, &save_chip[chips]->reg_output);
if (ret)
goto out_failed;
ret = pca9539_read_reg(save_chip[chips], PCA953X_DIRECTION, &save_chip[chips]->reg_direction);
if (ret)
goto out_failed;
ret = pca9539_write_reg(save_chip[chips], PCA953X_INVERT, 0);
if (ret)
goto out_failed;
i2c_set_clientdata(client, save_chip[chips]);
if(chips == 0) {
chips = 1;
}
else {
if(init_error == 0) {
ret = misc_register(&m502_gpio_miscdev);
if (ret)
goto out_failed;
#if defined(CONFIG_MACH_PAC4010)
for(ret = 0 ; ret < 8 ; ret++) {
M502_MODE[ret] = 1;
pca9539_gpio_direction_input(ret);
}
for(ret = 8 ; ret < 16 ; ret++) {
M502_MODE[ret] = 0;
pca9539_gpio_direction_output(ret,0,1);
}
for(ret = 23 ; ret < 25 ; ret++) {
pca9539_gpio_direction_output(ret , 1 , 0);
pca9539_gpio_set_value(ret , 1, 0);
}
#else
for(ret = 0 ; ret < M504_GPIO_COUNT ; ret++) {
M502_MODE[ret] = 1;
at91_set_gpio_input(M502_GPIO[ret], 0);
}
if(M504_GPIO_SW != 0) {
for(ret = M504_GPIO_COUNT ; ret < M504_TOTAL_GPIO ; ret++)
at91_set_gpio_input(M502_GPIO[ret], 1);
}
printk("M502 GPIO Driver Ver 1.03 Loaded.\n");
/*START UART SETTING*/
#if defined(CONFIG_MACH_M502)
for(ret = 24 ; ret < 32 ; ret+=2) {
pca9539_gpio_direction_output(ret , 1 , 0);
pca9539_gpio_set_value(ret , 1, 0);
}
pca9539_gpio_direction_output(25 , 0 , 0);
pca9539_gpio_set_value(25 , 0 , 0);
#elif defined(CONFIG_MACH_MATRIX518)
for(ret = 23 ; ret < 32 ; ret++) {
pca9539_gpio_direction_output(ret , 1 , 0);
pca9539_gpio_set_value(ret , 1, 0);
}
#elif defined(CONFIG_MACH_MATRIX522)
for(ret = 23 ; ret < 25 ; ret++) {
pca9539_gpio_direction_output(ret , 1 , 0);
pca9539_gpio_set_value(ret , 1, 0);
}
#endif
/*END UART SETTING*/
#endif
}
}
return 0;
out_failed:
init_error = 1;
if(chips == 0) {
chips = 1;
}
kfree(save_chip[chips]);
return ret;
}
static int pca9539_remove(struct i2c_client *client)
{
struct pca9539_chip *chip = i2c_get_clientdata(client);
misc_deregister(&m502_gpio_miscdev);
kfree(chip);
return 0;
}
static struct i2c_driver pca9539_driver = {
.driver = {
.name = "pca9539",
},
.probe = pca9539_probe,
.remove = pca9539_remove,
.id_table = pca9539_id,
};
static int __init m502_gpio_init(void)
{
return i2c_add_driver(&pca9539_driver);
}
static void __exit m502_gpio_exit(void)
{
i2c_del_driver(&pca9539_driver);
}
module_init(m502_gpio_init);
module_exit(m502_gpio_exit);
MODULE_LICENSE("GPL")
MODULE_AUTHOR("Ace Yang")
MODULE_DESCRIPTION("GPIO driver for M502 based on AT91SAM9G20")
next prev parent reply other threads:[~2012-03-21 14:41 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-20 13:28 [Xenomai-help] Linux Serial Does not work with CONFIG_XENO_OPT_PERVASIVE enabled Glen Wernersbach
2012-03-20 13:44 ` Philippe Gerum
2012-03-20 13:48 ` Glen Wernersbach
2012-03-20 13:57 ` Philippe Gerum
2012-03-20 14:07 ` Glen Wernersbach
2012-03-20 14:14 ` Philippe Gerum
2012-03-20 14:17 ` Philippe Gerum
2012-03-20 14:31 ` Philippe Gerum
2012-03-20 14:34 ` Glen Wernersbach
2012-03-20 14:47 ` Philippe Gerum
2012-03-20 14:53 ` Glen Wernersbach
2012-03-20 15:06 ` Philippe Gerum
2012-03-20 15:17 ` Glen Wernersbach
2012-03-20 15:24 ` Gilles Chanteperdrix
2012-03-20 15:27 ` Philippe Gerum
2012-03-20 16:09 ` Glen Wernersbach
2012-03-20 15:12 ` Gilles Chanteperdrix
2012-03-20 15:22 ` Glen Wernersbach
2012-03-20 15:26 ` Gilles Chanteperdrix
2012-03-20 16:40 ` Glen Wernersbach
2012-03-20 19:38 ` Gilles Chanteperdrix
2012-03-20 20:19 ` Glen Wernersbach
2012-03-20 20:35 ` Gilles Chanteperdrix
2012-03-20 21:20 ` Glen Wernersbach
2012-03-20 21:41 ` Philippe Gerum
2012-03-21 4:46 ` Glen Wernersbach
2012-03-21 7:43 ` Gilles Chanteperdrix
2012-03-21 13:21 ` Glen Wernersbach
2012-03-26 5:27 ` Glen Wernersbach
2012-03-21 8:38 ` Philippe Gerum
2012-03-21 14:41 ` Glen Wernersbach [this message]
2012-03-21 15:07 ` Philippe Gerum
2012-03-21 16:53 ` Glen Wernersbach
2012-03-20 16:22 ` Philippe Gerum
2012-03-20 16:32 ` Glen Wernersbach
2012-03-20 16:42 ` Gilles Chanteperdrix
2012-03-20 16:48 ` Glen Wernersbach
2012-03-20 14:50 ` Gilles Chanteperdrix
2012-03-20 14:59 ` Glen Wernersbach
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=CB8F60DA.1EE9B%glen@domain.hid \
--to=glen@domain.hid \
--cc=rpm@xenomai.org \
--cc=xenomai@xenomai.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.