[Soekris] 4801 GPIO
Steven Finnegan
sjf at ctrlsft.com
Tue Mar 20 13:50:06 UTC 2007
On Mar 19, 2007, at 13:25 , Peter Wood wrote:
> Heya Steven,
>
> Sorry to contact you off list, but I'm trying to do similar things
> to what you tried in January.
>
>> Is there something that needs to be done to program the GPIO pins
>> as outputs? Also, the "output bit numbers" (values put into
>> "ledxb") are not obvious. The 4801 manual shows the pc87366 pins
>> mapped to GPIO pins, with several apparent typos (GPIO24 and
>> GPIO26 are listed twice). I've tried both versions below, but
>> neither seems to work. Also, the error led is "20", which if the
>> pc87366 bit numbers are used would be GPIO 0 on pin #3. Although
>> I can flash the error led, NONE of the GPIO pins on JP5 are moving
>>
> Did anyone ever reply or did you manage to figure it out yourself?
> If you got somewhere would you mind sharing the pins that you used?
>
> Cheers,
>
> Peter.
>
Peter
Well, I was successful, after much work, in using the GPIO outputs.
It was NOT as simple as expanding on the error-led. The error-led
uses the CPU's gpio line, whereas the "GPIO output pins" use the
SuperIO chip's (PC87366) GPIO. So I had to figure out how to talk to
that device.
I have attached a patch file that will modify the geode.c file to
create gpio lines in the /dev/led directory. Hope this helps
*** geode.c.orig Wed Jan 31 15:24:28 2007
--- geode.c.new Thu Feb 1 13:19:20 2007
***************
*** 71,79 ****
--- 71,127 ----
static unsigned gpio;
static unsigned geode_counter;
+ /* begin sjf */
+ static unsigned sio_gpio;
+ static struct cdev* led[12];
+ static int ledb[12];
+ /* end sjf */
+
static struct cdev *led1, *led2, *led3;
static int led1b, led2b, led3b;
+ /* begin sjf */
+ static void sio_led_func( void *ptr, int onoff)
+ {
+ unsigned int u;
+ int bit;
+ int port;
+
+ bit = *(int *)ptr;
+ if (bit < 0) {
+ bit = -bit;
+ onoff = !onoff;
+ }
+
+ switch( bit & 0x70) // find proper port
+ {
+ default:
+ return; // improper port number
+ case 0x00:
+ port = sio_gpio + 0;
+ break;
+ case 0x10:
+ port = sio_gpio + 4;
+ break;
+ case 0x20:
+ port = sio_gpio + 8;
+ break;
+ case 0x30:
+ port = sio_gpio + 10;
+ break;
+ }
+
+ bit = bit & 0x07;
+
+ u = inb(port);
+ if (onoff)
+ u |= 1 << bit;
+ else
+ u &= ~(1 << bit);
+ outb(port, u);
+ }
+ /* end sjf */
+
static void
led_func(void *ptr, int onoff)
{
***************
*** 183,188 ****
--- 231,284 ----
printf("Geode GPIO@ = %x\n", gpio);
if ( bios_oem_strings(&bios_soekris,
bios_oem, BIOS_OEM_MAXLEN) >
0 ) {
+ /* begin sjf (SIO -> SuperIO device, PC87366)*/
+ #define SIO_INDEX 0x2e
+ #define SIO_DATA 0x2f
+ #define SIO_ID_ADD 0x20
+ #define SIO_ACTIVATE 0x30
+ #define SIO_ID 0xe9
+ #define SIO_DEVICE_REG 0x07
+ #define SIO_GPIO_DEV 0x07
+ #define SIO_IOPORT0HI 0x60
+ #define SIO_IOPORT0LO 0x61
+ #define SIO_GPIOPINSEL 0xf0
+ #define SIO_GPIOPINCONF 0xf1
+ int i;
+ outb( SIO_INDEX, SIO_ID_ADD);
+ i=inb(SIO_DATA);
+ if( i != SIO_ID)
+ printf( "SuperIO ID Failure 0x%x\n", i);
+ else
+ {
+ int pins[]={0x20, 0x21, 0x22, 0x23,
0x24, 0x25,
+ 0x26, 0x27, 0x04, 0x05, 0x13,
0x12};
+ char* name[] =
{"gpio00","gpio01","gpio02","gpio03","gpio04","gpio05",
+
"gpio06","gpio07","gpio08","gpio09","gpio10","gpio11"};
+ outb(SIO_INDEX, SIO_DEVICE_REG);
+ outb(SIO_DATA, SIO_GPIO_DEV); //
point to gpio device
+ // get GPIO address
+ outb(SIO_INDEX, SIO_IOPORT0HI);
+ sio_gpio = inb(SIO_DATA) << 8;
+ outb(SIO_INDEX, SIO_IOPORT0LO);
+ sio_gpio |= inb(SIO_DATA);
+ printf("Geode SIO_GPIO@ = %x\n",
sio_gpio);
+ outb(SIO_INDEX, SIO_ACTIVATE);
+ i=inb(SIO_DATA) & 0x01;
+ if( !i )
+ printf("SIO_GPIO not enabled
\n");
+ else
+ for( i=0; i<12; i++)
+ { /* setup the pins */
+ outb(SIO_INDEX,
SIO_GPIOPINSEL);
+ outb(SIO_DATA, pins
[i]); // select the pin
+ outb(SIO_INDEX,
SIO_GPIOPINCONF);
+ outb(SIO_DATA,
0x01); // Pullup off, Open drain, Out enab
+
+ ledb[i] = -pins[i];
+ led[i] = led_create
(sio_led_func, &ledb[i], name[i]);
+ }
+ }
+ /* end sjf */
led1b = 20;
led1 = led_create(led_func, &led1b, "error");
} else if ( bios_oem_strings(&bios_pcengines,
****************************
Controlsoft L.P.
Steven Finnegan
Web: www.ctrlsft.com
Email: sjf at ctrlsft.com
Phone: 972-540-9935
****************************
More information about the Soekris-tech
mailing list