net5501 __JP5__GPIO程序

/*
  direct GPIO access code for net5501 running linux
  Matthew Kaufman 3/24/2009, 4/1/2009
  Direct driverless access to PC87366 for GPIO and CS5536 for Error LED
  For register details see pgs 480 onward of:
    http://www.amd.com/files/connectivitysolutions/geode/geode_lx/33238G_cs5536_db.pdf
  And page 129 onward of:
    http://www.datasheetcatalog.org/datasheet/nationalsemiconductor/PC87366.pdf
  This is example code. A fancier version would make it easier to work with more than one
  pin at a time.
*/
    
#include <stdio.h>
#include <sys/io.h>
#define GPIO_BASE_CS5535   0x6100      /* rather than asking MSR_LBAR_GPIO which is harder to do */
#define SIO_INDEX            0x2e      /* index register of PC87366 Super I/O */
#define SIO_DATA             0x2f      /* data register of PC87366 Super I/O */
#define SIO_REG_SID          0x20      /* Configuration register containing ID */
#define SIO_SID_VALUE        0xe9      /* Expected ID value */
#define SIO_REG_LDN          0x07      /* Configuration register: logical device number selector */
#define SIO_LDN_GPIO         0x07      /* LDN Value to select GPIO configuration */
#define SIO_REG_ACTIVATE     0x30      /* (Shared) Device register: Activate */
#define SIO_REG_BASE_MSB_0   0x60      /* (Shared) Device register: I/O Port base, descriptor 0, MSB */
#define SIO_REG_BASE_LSB_0   0x61      /* (Shared) Device register: I/O Port base, descriptor 0, LSB */
#define SIO_GPIO_PIN_SELECT  0xf0      /* GPIO device-specific register: Pin select */
#define SIO_GPIO_PIN_CONFIG  0xf1      /* GPIO device-specific register: Pin configuration */
int gpio_base = 0;
int pin_init()
{
    int i;
    if(iopl(3)) /* allow direct I/O access at 0x2e, 0x6100, 0x6640 and thereabouts. must be root. */
        return -1;
    outb(SIO_REG_SID, SIO_INDEX);   /* probe PC87366 */
    i = inb(SIO_DATA);
    if(i != SIO_SID_VALUE)
        return -1;
    outb(SIO_REG_BASE_MSB_0, SIO_INDEX);    /* get MSB of GPIO I/O */
    gpio_base = inb(SIO_DATA) << 8;
    outb(SIO_REG_BASE_LSB_0, SIO_INDEX);    /* get LSB of GPIO I/O */
    gpio_base |= inb(SIO_DATA);
    /* turn on GPIO */
    /* Note: the pin configuration calls assume that this logical device select hasn't been overridden */
    /* if that's a problem in practice, the next two lines must be added to the _pin_config function   */
    outb(SIO_REG_LDN, SIO_INDEX);     /* logical device select */
    outb(SIO_LDN_GPIO, SIO_DATA);     /* select GPIO */
    outb(SIO_REG_ACTIVATE, SIO_INDEX); /* activation for selected device, which is GPIO */
    outb(0x01, SIO_DATA);              /* active */
    return 0;
}
void error_led_set()
{
    /* error LED is GPIO 6 on the CS5535 */
    outl(1 << 6, GPIO_BASE_CS5535); /* using CS5535 atomic set */
}
void error_led_clear()
{
    outl(1 << (6+16), GPIO_BASE_CS5535); /* using CS5535 atomic clear */
}
static int _pin_to_gpio(int pin)
{
    /* mapping table from email by Ralph Becker-Szendy */
    switch(pin)
    {
    case 3: return 16;
    case 4: return 17;
    case 5: return 18;
    case 6: return 19;
    case 7: return 20;
    case 8: return 21;
    case 9: return 22;
    case 10: return 23;
    case 12: return 4;
    case 13: return 5;
    case 15: return 11;
    case 16: return 10;
    default: return -1;
    }
}
int pin_test(int pin)
{
    int gpio = _pin_to_gpio(pin);
    int offset;
    int i;
    if(gpio < 0)
        return;
    if(gpio >= 16)
        offset = 0x09;
    else if(gpio >= 8)
        offset = 0x05;
    else
        offset = 0x01;
    i = inb(gpio_base + offset);
    return(i & (1 << (gpio & 0x07)));
}
      
void pin_set_to(int pin, int set)
{
    int gpio = _pin_to_gpio(pin);
    int offset;
    int i;
    if(gpio_base == 0)
        return; /* not initialized */
    if(gpio < 0)
        return;
    if(gpio >= 16)
        offset = 0x08;
    else if(gpio >= 8)
        offset = 0x04;
    else
        offset = 0x00;
    i = inb(gpio_base + offset);
    if(set)
    {
        i |= 1 << (gpio & 0x07);
    }
    else
    {
        i &= ~(1 << (gpio & 0x07));
    }
    outb(i, gpio_base + offset);
}
void pin_set(int pin)
{
    pin_set_to(pin, 1);
}
void pin_clear(int pin)
{
    pin_set_to(pin, 0);
}
static void _pin_config(int pin, int bit, int set)
{
    int gpio = _pin_to_gpio(pin);
    int i;
    if(gpio_base == 0)
        return; /* not initialized */
    if(gpio < 0)
        return;
    /* See note above about how we assume GPIO logical device is already selected */
    outb(SIO_GPIO_PIN_SELECT, SIO_INDEX);
    outb(((gpio & 0x38) << 1) | (gpio & 0x07), SIO_DATA);
    outb( SIO_GPIO_PIN_CONFIG, SIO_INDEX);
    i = inb(SIO_DATA);
    if(set)
    {
        i |= 1 << bit;
    }
    else
    {
        i &= ~(1 << bit);
    }
    outb( i, SIO_DATA);
}
void pin_output_enable(int pin)
{
    _pin_config(pin, 0, 1);
}
void pin_output_disable(int pin)
{
    _pin_config(pin, 0, 0);
}
void pin_output_pushpull(int pin)
{
    _pin_config(pin, 1, 1);
}
void pin_output_opendrain(int pin)
{
    _pin_config(pin, 1, 0);
}
void pin_output_pullup_enable(int pin)
{
    _pin_config(pin, 2, 1);
}
void pin_output_pullup_disable(int pin)
{
    _pin_config(pin, 2, 0);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值