Hi all,
Signed-off: Marc Bertens <[email protected]>
Tested-by: Marc Bertens<[email protected]>
I made some new patches for the Nokia IP530, therefore my last patch
submission can be discarded.
1. 21143PD driver; I removed the not needed stuff from there and
tested without and all worked fine.
2. Patched the devicetree.cb; added some comments and commented out
the setting of the GPIO lines, this was unnecessary.
3. nokia/Kconfig; added a description in de help about which board
revisions are supported.
4. ip530/Kconfig; added the CPU model, removed the PIRQ_ROUTE and set
the IRQ_SLOT_COUNT to 1, this last is needed by the
header files, because those structures are still used by the
code, see pirq_table.c
5. ip530/mainboard.c; Now the identification of the physical system
is show in the boot up of the machine, like;
* System type, should be IP530, otherwise a warning is given.
* Board number
* Mfg. P/N
* Mfg. rev.
* Serial number
All these read from the SPI eeprom behind the SuperIO
6. The sourcecode files for the superIO-SPI interface in the
Nokia-IP530.
Stefan: please drop that last patch submission of mine.
Thats all folks....
Marc
Index: src/drivers/dec/21143/21143.c
===================================================================
--- src/drivers/dec/21143/21143.c (revision 6292)
+++ src/drivers/dec/21143/21143.c (working copy)
@@ -27,20 +27,6 @@
static void dec_21143_enable(device_t dev)
{
printk(BIOS_DEBUG, "Initializing DECchip 21143\n");
-
- // The resource allocator should do this. If not, it needs to be fixed
- // differently.
-#if 0
- /* Command and status configuration (offset 0x04) */
- pci_write_config32(dev, 0x04, 0x02800107);
- printk(BIOS_DEBUG, "0x04 = %08x (07 01 80 02)\n",
- pci_read_config32(dev, 0x04));
-
- /* Cache line size (offset 0x0C) */
- pci_write_config8(dev, 0x0C, 0x00);
- printk(BIOS_DEBUG, "0x0c = %08x (00)\n",
- pci_read_config8(dev, 0x0C));
-#endif
}
static struct device_operations dec_21143_ops = {
Index: src/mainboard/nokia/ip530/devicetree.cb
===================================================================
--- src/mainboard/nokia/ip530/devicetree.cb (revision 6292)
+++ src/mainboard/nokia/ip530/devicetree.cb (working copy)
@@ -51,13 +51,14 @@
irq 0xB2 = 0x0C # Soft power status 1
irq 0xB3 = 0x05 # Soft power status 2
irq 0xC0 = 0x03 # IRQ MUX control
-
+ # setting up the PINs to there function, ie. GPIO, IRQ or other function
irq 0xC8 = 0x10 # GP50 = (I/O) output = Flashrom enable
irq 0xCA = 0x09 # GP52 = IRQ8 (output)
irq 0xCB = 0x01 # GP53 = nROMCS (output)
irq 0xCC = 0x11 # GP54 = (I/O) input
- irq 0xF9 = 0x00 # read/write GP5x lines (0x1C)
-
+## This line can go !!!!
+# irq 0xF9 = 0x00 # read/write GP5x lines (0x1C)
+ # setting up the PINs to there function, ie. GPIO, IRQ or other function
irq 0xD0 = 0x08 # GP60 = IRQ1
irq 0xD1 = 0x08 # GP61 = IRQ3
irq 0xD2 = 0x08 # GP62 = IRQ4
@@ -66,17 +67,19 @@
irq 0xD5 = 0x11 # GP65 = (I/O) input
irq 0xD6 = 0x08 # GP66 = IRQ8
irq 0xD7 = 0x11 # GP67 = (I/O) input
- irq 0xFA = 0x00 # read/write GP6x lines (0x88)
-
- irq 0xE0 = 0x00 # GP10 (I/O) = output
- irq 0xE1 = 0x01 # GP11 (I/O) = input
+## This line can go !!!!
+# irq 0xFA = 0x00 # read/write GP6x lines (0x88)
+ # setting up the PINs to there function, ie. GPIO, IRQ or other function
+ irq 0xE0 = 0x00 # GP10 (I/O) = output to DI of 93LC46 (1024 bits of EEPROM)
+ irq 0xE1 = 0x01 # GP11 (I/O) = input from DO of 93LC46
+ irq 0xE4 = 0x00 # GP14 (I/O) = output to SK of 93LC46
+ irq 0xE5 = 0x00 # GP15 (I/O) = output to CS of 93LC46
irq 0xE2 = 0x08 # GP12 = P17
irq 0xE3 = 0x00 # GP13 (I/O) = output = LED fault on front, active low
- irq 0xE4 = 0x00 # GP14 (I/O) = output
- irq 0xE5 = 0x00 # GP15 (I/O) = output
irq 0xE6 = 0x01 # GP16 (I/O) = input = JP900 on board, low on short, high on open
irq 0xE7 = 0x00 # GP17 (I/O) = output = LED alert on front, active low
- irq 0xF6 = 0xFF # read/write GP1x lines (0xCA)
+ # Make sure that the LEDs are off and set all EEPROM lines HIGH
+ irq 0xF6 = 0xAC # read/write GP1x lines (0xCA)
irq 0xEF = 0x00 # GP_INT2 disable
irq 0xF0 = 0x00 # GP_INT1 disable
Index: src/mainboard/nokia/ip530/Kconfig
===================================================================
--- src/mainboard/nokia/ip530/Kconfig (revision 6292)
+++ src/mainboard/nokia/ip530/Kconfig (working copy)
@@ -22,13 +22,13 @@
def_bool y
select ARCH_X86
select CPU_INTEL_SOCKET_PGA370
+ select CPU_INTEL_MODEL_68X
select NORTHBRIDGE_INTEL_I440BX
select SOUTHBRIDGE_INTEL_I82371EB
select SUPERIO_SMSC_SMSCSUPERIO
select SOUTHBRIDGE_TI_PCI1X2X
select DRIVERS_DEC_21143
select BOARD_ROMSIZE_KB_512
- select PIRQ_ROUTE
select HAVE_PIRQ_TABLE
select UDELAY_TSC
select SDRAMPWR_4DIMM
@@ -43,7 +43,7 @@
config IRQ_SLOT_COUNT
int
- default 22
+ default 1
## Configuration for the PCMCIA-Cardbus controller.
config TI_PCMCIA_CARDBUS_CMDR
Index: src/mainboard/nokia/ip530/mainboard.c
===================================================================
--- src/mainboard/nokia/ip530/mainboard.c (revision 6292)
+++ src/mainboard/nokia/ip530/mainboard.c (working copy)
@@ -21,6 +21,48 @@
#include <device/device.h>
#include "chip.h"
+#include <console/console.h>
+#include <stdlib.h> // get some memory
+#include <delay.h> // mdelay()
+#include <string.h> // memcmp() coreboots version
+#define CONFIG_USES_93LC46_16BIT
+#include "microchip93lc46b_spi.c"
+#include "superio.c"
+#include "superio_spi.c"
+
+static void enable_nokia( struct device *dev )
+{
+ uint8_t i;
+ uint8_t* szString = malloc( 0x10 );
+ spi_93LC46B_read( 0, szString, 6 );
+ if ( memcmp( szString, "IP530\0", 6 ) != 0 )
+ {
+ printk( BIOS_CRIT, "This is not a NOKIA - IP530, but a %s\n", szString );
+ return;
+ }
+ /* Ok its a NOKIA-IP530 */
+ printk( BIOS_INFO, "NOKIA : %s", szString );
+ /* Board number, sticker close to the PIII cpu */
+ spi_93LC46B_read( 0x24, szString, 6 );
+ printk( BIOS_INFO, "\nBoard number : " );
+ for ( i = 0; i < 6; i++ )
+ {
+ printk( BIOS_INFO, "%02X", szString[ i ] & 0xFF );
+ }
+ /* Mfg. P/n (on the bottom side of the unit), filled out with spaces */
+ spi_93LC46B_read( 0x2A, szString, 14 );
+ printk( BIOS_INFO, "\nMfg. P/N : %s", szString );
+ /* Mfg. rev. (on the bottom side of the unit), 0xYY = is the revision letter, where A = 0x41, B = 0x42 */
+ spi_93LC46B_read( 0x3E, szString, 2 );
+ printk( BIOS_INFO, "\nMfg. rev. : %s", szString );
+ /* Serial number (on the bottom side of the unit) */
+ spi_93LC46B_read( 0x52, szString, 12 );
+ printk( BIOS_INFO, "\nSerial number : %s\n", szString );
+ free( szString );
+ return;
+}
+
struct chip_operations mainboard_ops = {
CHIP_NAME("Nokia IP530 Mainboard")
+ .enable_dev = enable_nokia,
};
Index: src/mainboard/nokia/ip530/irq_tables.c
===================================================================
--- src/mainboard/nokia/ip530/irq_tables.c (revision 6292)
+++ src/mainboard/nokia/ip530/irq_tables.c (working copy)
@@ -17,80 +17,249 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
#include <arch/pirq_routing.h>
+#include <console/console.h>
+#define CONFIG_USES_93LC46_16BIT
+#include "microchip93lc46b_spi.h"
+#include <stdint.h>
+#include <string.h> // memcmp() coreboots version
+/*
+ * This IRQ mask enables the following lines 5, 6, 10, 11
+ * IRQ-lines FEDCBA9876543210
+ * 0x1E20 = 0001111000100000
+ * 0x0C60 = 0000110001100000 (current)
+ */
+#define PIRQ_IRQ_MASK 0x0C60
+static uint8_t BoardRevision[ 2 ];
-#define PIRQ_IRQ_MASK 0x0c60
+static struct irq_routing_table* build_pirq_table( unsigned long addr, uint16_t router_bus, uint16_t dev,
+ uint16_t sub_dev, uint16_t router_dev )
+{
+ struct irq_routing_table *pirq;
+ /* Align the table to be 16 byte aligned. */
+ addr += 15;
+ addr &= ~15;
+ printk( BIOS_INFO, "Address correction on dynamic IRQ routing tables to 0x%lx\n", addr );
+ pirq = (void *)(addr);
+ /* u32 signature */
+ pirq->signature = PIRQ_SIGNATURE;
+ /* u16 version */
+ pirq->version = PIRQ_VERSION;
+ /* Interrupt router bus */
+ pirq->rtr_bus = router_bus;
+ /* Interrupt router device. */
+ pirq->rtr_devfn = router_dev;
+ /* IRQs devoted exclusively to PCI usage */
+ pirq->exclusive_irqs = 0;
+ /* Vendor */
+ pirq->rtr_vendor = dev;
+ /* Device */
+ pirq->rtr_device = sub_dev;
+ /* Miniport */
+ pirq->miniport_data = 0;
+ /* u8 rfu[11] */
+ memset( pirq->rfu, 0, sizeof( pirq->rfu ) );
+ pirq->checksum = 0;
+ return ( pirq );
+}
-const struct irq_routing_table intel_irq_routing_table = {
- PIRQ_SIGNATURE, /* u32 signature */
- PIRQ_VERSION, /* u16 version */
- 32 + 16 * CONFIG_IRQ_SLOT_COUNT,/* Max. number of devices on the bus */
- 0x00, /* Interrupt router bus */
- (0x07 << 3) | 0x0, /* Interrupt router dev */
- 0, /* IRQs devoted exclusively to PCI usage */
- 0x8086, /* Vendor */
- 0x122e, /* Device */
- 0, /* Miniport */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
- 0xD7, /* Checksum */
+static void finish_pirw_table( struct irq_routing_table* pirq, uint8_t slots )
+{
+ uint16_t i;
+ uint8_t sum = 0;
+ uint8_t* v = (uint8_t *)(pirq);
+ printk( BIOS_SPEW, "PIRQ slots %i\n", slots & 0xFF );
+ pirq->size = 32 + 16 * slots;
+ printk( BIOS_SPEW, "PIRQ table size %i\n", pirq->size );
+ for ( i = 0; i < pirq->size; i++ )
{
- /**
- * Rebuild of the PIRQ table, to fix the non-working on-board NIC and PCMCIA controller.
- * FEDCBA9876543210
- * 0x1E20 = 0001111000100000
- * 0x0C60 = 0000110001100000
- */
- // Southbridge 82371EB, INTD = 0x63
- { 0x00, (0x07 << 3) | 0x0, {{0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}}, 0x0, 0x0 },
- // On-board PCI-to-PCI bridge
- { 0x01, (0x00 << 3) | 0x0, {{0x60, PIRQ_IRQ_MASK}, {0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}}, 0x0, 0x0 },
- // ETH1 on front panel, INTA = 0x62 = ok
- { 0x00, (0x0d << 3) | 0x0, {{0x62, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}}, 0x0, 0x0 },
-
- // ETH2 on front panel, 0x63
- { 0x00, (0x0e << 3) | 0x0, {{0x63, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}}, 0x0, 0x0 },
- // ETH3 on front panel = 0x60
- { 0x02, (0x04 << 3) | 0x0, {{0x60, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}}, 0x0, 0x0 },
-
- // ETH4 on front panel, INTA = 0x61 = ok
- { 0x02, (0x05 << 3) | 0x0, {{0x61, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}}, 0x0, 0x0 },
- // PCMCIA/Cardbus controller, INTA = 0x60 = ok, INTB = 0x61 = ok
- { 0x00, (0x0f << 3) | 0x0, {{0x60, PIRQ_IRQ_MASK}, {0x61, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}, {0x00, PIRQ_IRQ_MASK}}, 0x0, 0x0 },
- // Bridge for slot 1 (top)
- { 0x02, (0x07 << 3) | 0x0, {{0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}, {0x64, PIRQ_IRQ_MASK}}, 0x0, 0x0 },
- // PCI compact slots 1 (top)
- { 0x03, (0x04 << 3) | 0x0, {{0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}, {0x60, PIRQ_IRQ_MASK}}, 0x1, 0x0 },
- { 0x03, (0x05 << 3) | 0x0, {{0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}, {0x60, PIRQ_IRQ_MASK}, {0x61, PIRQ_IRQ_MASK}}, 0x2, 0x0 },
- { 0x03, (0x06 << 3) | 0x0, {{0x63, PIRQ_IRQ_MASK}, {0x60, PIRQ_IRQ_MASK}, {0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}}, 0x3, 0x0 },
- { 0x03, (0x07 << 3) | 0x0, {{0x60, PIRQ_IRQ_MASK}, {0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}}, 0x4, 0x0 },
- // Bridge for slot 2 (middle)
- { 0x02, (0x06 << 3) | 0x0, {{0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}, {0x60, PIRQ_IRQ_MASK}}, 0x0, 0x0 },
- // PCI compact slots 2 (middle)
- { 0x04, (0x04 << 3) | 0x0, {{0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}, {0x60, PIRQ_IRQ_MASK}}, 0x5, 0x0 },
- { 0x04, (0x05 << 3) | 0x0, {{0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}, {0x60, PIRQ_IRQ_MASK}, {0x61, PIRQ_IRQ_MASK}}, 0x6, 0x0 },
- { 0x04, (0x06 << 3) | 0x0, {{0x63, PIRQ_IRQ_MASK}, {0x60, PIRQ_IRQ_MASK}, {0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}}, 0x7, 0x0 },
- { 0x04, (0x07 << 3) | 0x0, {{0x60, PIRQ_IRQ_MASK}, {0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}}, 0x8, 0x0 },
- // Bridge for slot 3 (bottom)
- { 0x00, (0x10 << 3) | 0x0, {{0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}, {0x60, PIRQ_IRQ_MASK}}, 0x0, 0x0 },
- // PCI compact slots 3 (bottom)
- { 0x05, (0x04 << 3) | 0x0, {{0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}, {0x60, PIRQ_IRQ_MASK}}, 0x9, 0x0 },
- { 0x05, (0x05 << 3) | 0x0, {{0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}, {0x60, PIRQ_IRQ_MASK}, {0x61, PIRQ_IRQ_MASK}}, 0xA, 0x0 },
- { 0x05, (0x06 << 3) | 0x0, {{0x63, PIRQ_IRQ_MASK}, {0x60, PIRQ_IRQ_MASK}, {0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}}, 0xB, 0x0 },
- { 0x05, (0x07 << 3) | 0x0, {{0x60, PIRQ_IRQ_MASK}, {0x61, PIRQ_IRQ_MASK}, {0x62, PIRQ_IRQ_MASK}, {0x63, PIRQ_IRQ_MASK}}, 0xC, 0x0 },
+ sum += v[ i ];
}
-};
+ pirq->checksum = pirq->checksum - sum;
+ printk( BIOS_SPEW, "PIRQ checksum %02X\n", pirq->checksum & 0xFF );
+ return;
+}
-unsigned long write_pirq_routing_table(unsigned long addr)
+static void write_pirq_info_ex( struct irq_info *pirq_info, uint8_t bus, uint8_t devfn, uint8_t link0, uint16_t bitmap0,
+ uint8_t link1, uint16_t bitmap1, uint8_t link2, uint16_t bitmap2,uint8_t link3, uint16_t bitmap3,
+ uint8_t slot, uint8_t rfu)
{
- return copy_pirq_routing_table(addr);
+ pirq_info->bus = bus;
+ pirq_info->devfn = devfn;
+ pirq_info->irq[ 0 ].link = link0;
+ pirq_info->irq[ 0 ].bitmap = (link0 ? bitmap0 : 0x0000 );
+ pirq_info->irq[ 1 ].link = link1;
+ pirq_info->irq[ 1 ].bitmap = (link1 ? bitmap1 : 0x0000 );
+ pirq_info->irq[ 2 ].link = link2;
+ pirq_info->irq[ 2 ].bitmap = (link2 ? bitmap2 : 0x0000 );
+ pirq_info->irq[ 3 ].link = link3;
+ pirq_info->irq[ 3 ].bitmap = (link3 ? bitmap3 : 0x0000 );
+ pirq_info->slot = slot;
+ pirq_info->rfu = rfu;
+ return;
}
-/**
- * TODO: This stub function is here until the point is solved in the
- * main code of coreboot. See also arch/x86/boot/pirq_tables.c.
- */
-void pirq_assign_irqs(const unsigned char pIntAtoD[4])
+static void write_pirq_info( struct irq_info* pirq_info, uint8_t bus, uint8_t devfn,
+ uint16_t bitmap, uint8_t link0, uint8_t link1, uint8_t link2, uint8_t link3,
+ uint8_t slot )
{
+ write_pirq_info_ex( pirq_info, bus, devfn, link0, bitmap, link1, bitmap, link2, bitmap, link3, bitmap, slot, 0 );
return;
}
+
+#if CONFIG_MAXIMUM_CONSOLE_LOGLEVEL >= BIOS_SPEW
+static void HexDump( const char* pszCaption, const void* ptr, uint16_t size )
+{
+ int address = 0;
+ int j;
+ char Ascii[ 17 ];
+ const uint8_t* bytes = (const uint8_t*)ptr;
+ for ( address = 0, j = 0; address < size; address++ )
+ {
+ if ( j == 0 )
+ {
+ printk( BIOS_INFO, "\n%s:%p:%04X : ", pszCaption, (void*)(bytes + address), address );
+ }
+ if ( bytes[ address ] >= 0x20 && bytes[ address ] < 0x7E )
+ {
+ Ascii[ j ] = bytes[ address ];
+ }
+ else
+ {
+ Ascii[ j ] = '.';
+ }
+ printk( BIOS_INFO, "%02X ", bytes[ address ] & 0xFF );
+ if ( ++j == 16 )
+ {
+ Ascii[ j ] = 0;
+ printk( BIOS_INFO, "%s", Ascii );
+ j = 0;
+ }
+ }
+ if ( j != 0 )
+ {
+ Ascii[ j ] = 0;
+ for ( ; j < 16; j++ )
+ {
+ printk( BIOS_INFO, " " );
+ }
+ printk( BIOS_INFO, "%s", Ascii );
+ }
+ printk( BIOS_INFO, "\n" );
+ return;
+}
+#endif
+unsigned long write_pirq_routing_table( unsigned long addr )
+{
+ struct irq_routing_table *pirq;
+ struct irq_info *pirq_info;
+ unsigned slot_num = 0;
+ unsigned link;
+ unsigned domain;
+ /* Mfg. rev. (on the bottom side of the unit), 0xYY = is the revision letter, where A = 0x41, B = 0x42 */
+ spi_93LC46B_read( 0x3E, BoardRevision, 2 );
+ /* This table must be betweeen 0xf0000 & 0x100000 */
+ printk( BIOS_INFO, "Writing dynamic IRQ routing tables to 0x%lx...\n", addr );
+ /* For which board are we doing this */
+ printk( BIOS_INFO, "Nokia IP530 Mfg. rev. : %c\n", BoardRevision[ 0 ] );
+ /* memory, bus, device, sub-dev, interrupt router */
+ pirq = build_pirq_table( addr, 0x00, 0x8086, 0x122e, (0x07 << 3) | 0x0 );
+ pirq_info = (void *)( &pirq->checksum + 1);
+ printk( BIOS_SPEW, "Table Address : %p\n", pirq );
+ /* Southbridge 82371, INTD = 0x63 */
+ write_pirq_info( pirq_info, 0x00, (0x07<<3) | 0x0, PIRQ_IRQ_MASK, 0x00, 0x00, 0x00, 0x63, 0x00 );
+ pirq_info++; slot_num++;
+ // On-board PCI-to-PCI bridge */
+ write_pirq_info( pirq_info, 0x01, (0x00<<3) | 0x0, PIRQ_IRQ_MASK, 0x60, 0x61, 0x62, 0x63, 0x00 );
+ pirq_info++; slot_num++;
+ // ETH1 on front panel */
+ write_pirq_info( pirq_info, 0x00, (0x0d<<3) | 0x0, PIRQ_IRQ_MASK, 0x62, 0x00, 0x00, 0x00, 0x00 );
+ pirq_info++; slot_num++;
+ // ETH2 on front panel */
+ write_pirq_info( pirq_info, 0x00, (0x0e<<3) | 0x0, PIRQ_IRQ_MASK, 0x63, 0x00, 0x00, 0x00, 0x00 );
+ pirq_info++; slot_num++;
+ // ETH3 on front panel */
+ write_pirq_info( pirq_info, 0x02, (0x04<<3) | 0x0, PIRQ_IRQ_MASK, 0x60, 0x00, 0x00, 0x00, 0x00 );
+ pirq_info++; slot_num++;
+ // ETH4 on front panel */
+ write_pirq_info( pirq_info, 0x02, (0x05<<3) | 0x0, PIRQ_IRQ_MASK, 0x61, 0x00, 0x00, 0x00, 0x00 );
+ pirq_info++; slot_num++;
+ if ( BoardRevision[ 0 ] >= 'B' && BoardRevision[ 0 ] <= 'Z' )
+ {
+ if ( BoardRevision[ 0 ] > 'B' )
+ {
+ printk( BIOS_CRIT, "The %c revision of the Nokia IP530 are untested.\n", BoardRevision[ 0 ] );
+ }
+ /* PCMCIA/Cardbus controller, board revision B and higher */
+ write_pirq_info( pirq_info, 0x00, (0x0f<<3) | 0x0, PIRQ_IRQ_MASK, 0x60, 0x00, 0x00, 0x00, 0x00 );
+ }
+ else
+ {
+ /* PCMCIA/Cardbus controller, board revision A */
+ write_pirq_info( pirq_info, 0x00, (0x0f<<3) | 0x0, PIRQ_IRQ_MASK, 0x60, 0x61, 0x00, 0x00, 0x00 );
+ }
+ pirq_info++; slot_num++;
+ /* Bridge for slot 1 (top) */
+ write_pirq_info( pirq_info, 0x02, (0x07<<3) | 0x0, PIRQ_IRQ_MASK, 0x60, 0x61, 0x62, 0x63, 0x00 );
+ pirq_info++; slot_num++;
+ /* Bridge for slot 2 (middle) */
+ write_pirq_info( pirq_info, 0x02, (0x06<<3) | 0x0, PIRQ_IRQ_MASK, 0x60, 0x61, 0x62, 0x63, 0x00 );
+ pirq_info++; slot_num++;
+ /* Bridge for slot 3 (bottom) */
+ write_pirq_info( pirq_info, 0x00, (0x10<<3) | 0x0, PIRQ_IRQ_MASK, 0x60, 0x61, 0x62, 0x63, 0x00 );
+ pirq_info++; slot_num++;
+
+ for ( domain = 3; domain < 6; domain++ )
+ {
+ /* PCI compact slots 1 (top) = domain 3, 2 (middle) = domain 4, 3 (bottom) = domain 5 */
+ for ( link = 0; link < 4; link++ )
+ {
+ write_pirq_info( pirq_info, domain, ( ( 0x04 + link ) <<3 ) | 0x0, PIRQ_IRQ_MASK,
+ ( ( 0x61 + link ) & 0x63 ),
+ ( ( 0x62 + link ) & 0x63 ),
+ ( ( 0x63 + link ) & 0x63 ),
+ ( ( 0x60 + link ) & 0x63 ), 0x01 );
+ pirq_info++; slot_num++;
+ }
+ }
+ /* Fix the checksum of the table and set length */
+ finish_pirw_table( pirq, slot_num );
+ printk( BIOS_INFO, "Done dynamic IRQ routing tables.\n" );
+#if ( CONFIG_MAXIMUM_CONSOLE_LOGLEVEL >= BIOS_DEBUG )
+ printk( BIOS_INFO, "Signature : %08X\n", pirq->signature );
+ printk( BIOS_INFO, "Version : %04X\n", pirq->version );
+ printk( BIOS_INFO, "Sizeof PIRQ table : %u\n", pirq->size );
+ printk( BIOS_INFO, "Router bus : %02X\n", pirq->rtr_bus & 0xFF );
+ printk( BIOS_INFO, "Router device function : %02X\n", pirq->rtr_devfn & 0xFF );
+ printk( BIOS_INFO, "PCI IRQ's : %04x\n", pirq->exclusive_irqs & 0xFFFF );
+ printk( BIOS_INFO, "Router vendor id. : %04x\n", pirq->rtr_vendor );
+ printk( BIOS_INFO, "Router device id. : %04x\n", pirq->rtr_device );
+ printk( BIOS_INFO, "Miniport data : %04x\n", pirq->miniport_data );
+ printk( BIOS_INFO, "RFU bytes : " );
+ for ( slot_num = 0; slot_num < 10; slot_num++ )
+ {
+ printk( BIOS_INFO, "%02X ", pirq->rfu[ slot_num ] & 0xFF );
+ }
+ printk( BIOS_INFO, "\nChecksum : %02X\n", ( pirq->checksum & 0xFF ) );
+ for ( slot_num = 0; slot_num < (( pirq->size - 32 ) / 16); slot_num++ )
+ {
+ printk( BIOS_INFO, "\t{ %02X, %02X, { ", pirq->slots[ slot_num ].bus & 0xFF,
+ pirq->slots[ slot_num ].devfn & 0xFF );
+ for ( link = 0; link < 4; link++ )
+ {
+ printk( BIOS_INFO, "{ %02X, %04X }%c", pirq->slots[ slot_num ].irq[ link ].link,
+ pirq->slots[ slot_num ].irq[ link ].bitmap,
+ ( link < 3 ? ',' : ' ' ) );
+ }
+ printk( BIOS_INFO, "}, %02X, %02X }\n", pirq->slots[ slot_num ].slot & 0xFF,
+ pirq->slots[ slot_num ].rfu & 0xFF );
+ }
+ printk( BIOS_SPEW, "Table Address : %p\n", pirq );
+ if ( CONFIG_MAXIMUM_CONSOLE_LOGLEVEL >= BIOS_SPEW )
+ {
+ HexDump( "PIRQ", (uint8_t*)pirq, (uint16_t)((uint8_t*)pirq_info - (uint8_t*)pirq) );
+ }
+#endif
+ /* return the end of the table */
+ return ( (unsigned long)pirq_info );
+}
Index: src/mainboard/nokia/Kconfig
===================================================================
--- src/mainboard/nokia/Kconfig (revision 6292)
+++ src/mainboard/nokia/Kconfig (working copy)
@@ -23,6 +23,10 @@
config BOARD_NOKIA_IP530
bool "IP530"
+ help
+ The current coreboot release supports board manufacturer revision A and B.
+ Of the higher revisions is not known if all hardware is supported. We know
+ of revision F is running under a revision B coreboot bios.
endchoice
Index: src/mainboard/nokia/ip530/microchip93lc46b_spi.c
===================================================================
--- src/mainboard/nokia/ip530/microchip93lc46b_spi.c (revision 0)
+++ src/mainboard/nokia/ip530/microchip93lc46b_spi.c (revision 0)
@@ -0,0 +1,173 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 Marc Bertens
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#define CONFIG_USES_93LC46_16BIT
+#include "spi_interface.h"
+#include "microchip93lc46b_spi.h"
+/****************************************************************************
+ * This is written for usage within Coreboot, but can be used outside
+ * Coreboot as well.
+ *
+ ********/
+
+/**==========================================================================
+ * The defintion of the command table; opcode, address, direction and bit
+ * widths. This can easily adapted for other SPI eeproms. Currently the
+ * 93LC46 A/B/C types are supported. When using the C type depending on
+ * 8 or 16 modes (see ORG line in datasheet) use the A or B commands.
+ *
+ * When the 'address' contains 0xFFFF this means that the address is taken
+ * from the caller.
+ */
+static struct tag_spi_93LC46_eeprom_commands
+{
+ uint16_t opcode;
+ uint8_t opcode_width;
+ uint16_t address;
+ uint8_t address_width;
+ uint8_t data_width;
+ uint8_t direction;
+} COMMANDS[ SPI_93LC46_MAX_COMMANDS ] = {
+ { 0x0000, 0, 0x0000, 0, 0, 0 }, // SPI_CHIP_NULL_PLACEHOLDER
+#ifdef CONFIG_USES_93LC46_8BIT
+ { 0x0004, 3, 0x0000, 7, 0, 0 }, // SPI_EEPROM_WRITE_DISABLE
+ { 0x0004, 3, 0x0010, 7, 8, 0 }, // SPI_EEPROM_WRITE_ALL
+ { 0x0004, 3, 0x0020, 7, 0, 0 }, // SPI_EEPROM_ERASE_ALL
+ { 0x0004, 3, 0x0030, 7, 0, 0 }, // SPI_EEPROM_WRITE_ENABLE
+ { 0x0005, 3, 0xFFFF, 7, 8, 0 }, // SPI_EEPROM_WRITE
+ { 0x0006, 3, 0xFFFF, 7, 8, 1 }, // SPI_EEPROM_READ
+ { 0x0007, 3, 0xFFFF, 7, 0, 0 }, // SPI_EEPROM_ERASE
+#endif
+#ifdef CONFIG_USES_93LC46_16BIT
+ { 0x0004, 3, 0x0000, 6, 0, 0 }, // SPI_EEPROM_WRITE_DISABLE
+ { 0x0004, 3, 0x0010, 6, 16, 0 }, // SPI_EEPROM_WRITE_ALL
+ { 0x0004, 3, 0x0020, 6, 0, 0 }, // SPI_EEPROM_ERASE_ALL
+ { 0x0004, 3, 0x0030, 6, 0, 0 }, // SPI_EEPROM_WRITE_ENABLE
+ { 0x0005, 3, 0xFFFF, 6, 16, 0 }, // SPI_EEPROM_WRITE
+ { 0x0006, 3, 0xFFFF, 6, 16, 1 }, // SPI_EEPROM_READ
+ { 0x0007, 3, 0xFFFF, 6, 0, 0 }, // SPI_EEPROM_ERASE
+#endif
+};
+/**--------------------------------------------------------------------------
+ *
+ */
+uint16_t spi_93LC46_action( SPI_93LC46_CMDS eCmd, uint16_t addr, uint8_t* data )
+{
+ uint16_t address = addr;
+ SpiInterface.spi_start();
+ SpiInterface.spi_write( COMMANDS[ eCmd ].opcode_width, COMMANDS[ eCmd ].opcode );
+ if ( COMMANDS[ eCmd ].address != 0xFFFF )
+ {
+ address = COMMANDS[ eCmd ].address;
+ }
+ SpiInterface.spi_write( COMMANDS[ eCmd ].address_width, address );
+ if ( COMMANDS[ eCmd ].data_width > 0 )
+ {
+ uint8_t len = COMMANDS[ eCmd ].data_width;
+ uint8_t off = 0;
+ if ( COMMANDS[ eCmd ].direction == 0 )
+ {
+ while ( len )
+ {
+ // Write the data to the device
+ SpiInterface.spi_write( 8, data[ off++ ] );
+ len -= 8;
+ }
+ SpiInterface.spi_wait_for_ready();
+ }
+ else
+ {
+ while ( len )
+ {
+ // Read the data from the device
+ data[ off ] = SpiInterface.spi_read( 8 );
+ off++;
+ len -= 8;
+ }
+ }
+ }
+ SpiInterface.spi_stop();
+ return ( COMMANDS[ eCmd ].data_width );
+}
+#ifdef CONFIG_USES_93LC46_8BIT
+/**--------------------------------------------------------------------------
+ *
+ */
+void spi_93LC46A_read( int address, uint8_t *bytes, uint16_t size ) // the length of 'bytes' must be divideble by 2 !!!
+{
+ uint16_t i;
+ for ( i = 0; i < size; i++ )
+ {
+ spi_93LC46_action( SPI_93LC46A_READ, address + i, bytes + i );
+ }
+ return;
+}
+/**--------------------------------------------------------------------------
+ *
+ */
+void spi_93LC46A_write( int address, uint8_t *bytes, uint16_t size ) // the length of 'bytes' must be divideble by 2 !!!
+{
+ uint16_t i;
+ spi_93LC46A_enable_wr();
+ for ( i = 0; i < size; i++ )
+ {
+ spi_93LC46_action( SPI_93LC46A_WRITE, address + i, bytes + i )
+ }
+ spi_93LC46A_disable_wr();
+ return;
+}
+#endif
+#ifdef CONFIG_USES_93LC46_16BIT
+/**--------------------------------------------------------------------------
+ *
+ */
+void spi_93LC46B_read( int address, uint8_t *bytes, uint16_t size ) // the length of 'bytes' must be divideble by 2 !!!
+{
+ uint16_t i;
+ address /= 2;
+ for ( i = 0; i < size; i++ )
+ {
+ if ( spi_93LC46_action( SPI_93LC46B_READ, address + (i / 2), bytes + i ) == 16 )
+ {
+ i++;
+ }
+ }
+ return;
+}
+/**--------------------------------------------------------------------------
+ *
+ */
+void spi_93LC46B_write( int address, uint8_t *bytes, uint16_t size ) // the length of 'bytes' must be divideble by 2 !!!
+{
+ uint16_t i;
+ spi_93LC46B_enable_wr();
+ address /= 2;
+ for ( i = 0; i < size; i++ )
+ {
+ if ( spi_93LC46_action( SPI_93LC46B_WRITE, address + (i / 2), bytes + i ) == 16 )
+ {
+ i++;
+ }
+ }
+ spi_93LC46B_disable_wr();
+ return;
+}
+#endif
+/**--------------------------------------------------------------------------
+ * END
+ */
Index: src/mainboard/nokia/ip530/spi_interface.h
===================================================================
--- src/mainboard/nokia/ip530/spi_interface.h (revision 0)
+++ src/mainboard/nokia/ip530/spi_interface.h (revision 0)
@@ -0,0 +1,26 @@
+#ifndef __SPI_INTERFACE_H__
+#define __SPI_INTERFACE_H__
+#include <stdint.h>
+
+typedef struct tag_spi_bitfunctions
+{
+ int (*spi_init)( uint16_t port, int spi_delay );
+ /* This function generates a START condition on the SPI bus */
+ void (*spi_start)( void );
+ /* This function generates a STOP condition on the SPI bus */
+ void (*spi_stop)( void );
+ /* This function creates a STOP condition and waits on the SPI slave to
+ * release the SPI bus. */
+ void (*spi_wait_for_ready)( void );
+ /* This function takes care of the writing of the specified number of bits */
+ void (*spi_write)( int8_t bits, int command );
+ /* This function takes care of the reading of the specified number of bits */
+ int (*spi_read)( int8_t bits );
+} SPI_INTF_FUNCTIONS;
+
+/*
+ * This must be defined by the user, with its own SPI routines
+ */
+extern SPI_INTF_FUNCTIONS SpiInterface;
+
+#endif
Index: src/mainboard/nokia/ip530/superio_spi.c
===================================================================
--- src/mainboard/nokia/ip530/superio_spi.c (revision 0)
+++ src/mainboard/nokia/ip530/superio_spi.c (revision 0)
@@ -0,0 +1,249 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 Marc Bertens
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+//#include <errno.h>
+//#include <stdlib.h>
+//#include <string.h> // for strcmp()
+#include <stdint.h>
+#include "superio.h"
+#ifndef CONFIG_BOARD_NOKIA_IP530
+#include "superio_spi.h"
+#endif
+#include "spi_interface.h"
+
+/****************************************************************************
+ * This is written for usage within Coreboot, but can be used outside
+ * Coreboot as well. It accesses the SPI eeprom behind the SuperIO chip.
+ * It uses the bitbang mechanism to control the SPI bus.
+ *
+ ********/
+
+/**--------------------------------------------------------------------------
+ * Cached value of last GPIO state.
+ */
+static uint8_t bGpioState = 0;
+#ifdef CONFIG_BOARD_NOKIA_IP530
+/* When compiling into Coreboot for the Nokia IP530 don't bother having those
+ * values configurable */
+# define iSuperIoPort 0x3F0
+# define iSpiHalfPeriod 0
+/* Use Coreboots delay function */
+# define spi_delay( d ) mdelay( d )
+#else
+/* Address of Super I/O chip */
+uint16_t iSuperIoPort = 0x3F0;
+/* Half a period delay */
+int iSpiHalfPeriod = 0;
+
+/**--------------------------------------------------------------------------
+ * loops per microsecond
+ */
+static void spi_delay( int usecs )
+{
+ static unsigned long micro = 1;
+ unsigned long i;
+ for (i = 0; i < usecs * micro; i++) {
+ /* Make sure the compiler doesn't optimize the loop away. */
+ asm volatile ("" : : "rm" (i) );
+ }
+ return;
+}
+#endif
+/**--------------------------------------------------------------------------
+ * This function sets the SuperIO into config mode, selects Logical Device
+ * eight (8 = GPIO Device) and reads the GPIO line register.
+ */
+static void superio_access_spibus( void )
+{
+ superio_acquire_configmode( iSuperIoPort );
+ /* select the Logical Device Number <ldn> */
+ superio_write_reg( iSuperIoPort, SUPERIO_LDN_REG, SUPERIO_LDN_GPIO );
+ /* Update the cache. */
+ bGpioState = superio_read_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG );
+ return;
+}
+/**--------------------------------------------------------------------------
+ * This function takes care of the reading of the specified number of bits
+ *
+ * +-----+
+ * | | |
+ * --+ +-----+
+ * 1 2 3 4
+ * A B C D
+ */
+static int superio_spi_read( int8_t bits )
+{
+ int ret = 0;
+ int i;
+ superio_access_spibus();
+ for ( i = bits-1; i >= 0; i-- )
+ {
+ /* Wait A */
+ spi_delay( iSpiHalfPeriod );
+ /* Step 1: pullup SCK line */
+ bGpioState |= SPI_SCK;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ /* Wait B */
+ spi_delay( iSpiHalfPeriod );
+ ret <<= 1;
+ /* Step 2: Get the MISO line state */
+ bGpioState = superio_read_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG );
+ ret |= (((bGpioState & SPI_MISO) == SPI_MISO)& 0x01);
+ /* Wait C */
+ spi_delay( iSpiHalfPeriod );
+ /* pulldown SCK line */
+ bGpioState &= ~SPI_SCK;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ /* Wait D */
+ spi_delay( iSpiHalfPeriod );
+ }
+ superio_release_configmode( iSuperIoPort );
+ return ( ret );
+}
+/**--------------------------------------------------------------------------
+ * This function takes care of the writing of the specified number of bits
+ *
+ * +-----+
+ * | | |
+ * --+ +-----+
+ * 1 2 3
+ * A B C D
+ */
+static void superio_spi_write( int8_t bits, int data )
+{
+ int i;
+ superio_access_spibus();
+ for ( i = bits-1; i >= 0; i-- )
+ {
+ /* Step 1: Set the MOSI line state */
+ if ( (data >> i) & 0x01 )
+ bGpioState |= SPI_MOSI;
+ else
+ bGpioState &= ~SPI_MOSI;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ /* Wait A */
+ spi_delay( iSpiHalfPeriod );
+ /* Step 2: pullup SCK line */
+ bGpioState |= SPI_SCK;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ /* Wait B */
+ spi_delay( iSpiHalfPeriod );
+ /* Wait C */
+ spi_delay( iSpiHalfPeriod );
+ /* Step 3: pulldown SCK line */
+ bGpioState &= ~SPI_SCK;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ /* Wait D */
+ spi_delay( iSpiHalfPeriod );
+ }
+ superio_release_configmode( iSuperIoPort );
+ return;
+}
+/**--------------------------------------------------------------------------
+ * This function creates a STOP condition and waits on the SPI slave to
+ * release the SPI bus.
+ */
+static void superio_spi_wait_for_ready( void )
+{
+ uint16_t j;
+ superio_access_spibus();
+ /* Generate a COMMIT condition.
+ * pulldown CS line */
+ bGpioState &= ~SPI_CS;
+ /* pullup SCK line */
+ bGpioState |= SPI_SCK;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ spi_delay( iSpiHalfPeriod );
+ /* pullup CS line */
+ bGpioState |= SPI_CS;
+ /* pulldown SCK line */
+ bGpioState &= ~SPI_SCK;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ spi_delay( iSpiHalfPeriod );
+ /* Wait for the SLAVE */
+ do
+ {
+ /* pullup SCK line */
+ bGpioState |= SPI_SCK;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ spi_delay( iSpiHalfPeriod );
+ /* Update the cache. */
+ bGpioState = superio_read_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG );
+ j = ((bGpioState & SPI_MISO) == SPI_MISO);
+ spi_delay( iSpiHalfPeriod );
+ /* pulldown SCK line */
+ bGpioState &= ~SPI_SCK;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ spi_delay( iSpiHalfPeriod );
+ }
+ while ( !j );
+ superio_release_configmode( iSuperIoPort );
+ return;
+}
+/**--------------------------------------------------------------------------
+ * This function generates a START condition on the SPI bus
+ */
+static void superio_spi_start( void )
+{
+ superio_access_spibus();
+ /* Check of the MISO and SCK lines are NOT down */
+ if ( bGpioState & ( SPI_MISO | SPI_SCK ) )
+ {
+ /* SPI bus is wrong state
+ * Pull down the CS, SCK and MOSI lines */
+ bGpioState &= ~SPI_CS_SCK_MOSI;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ spi_delay( iSpiHalfPeriod );
+ }
+ /* Generate the START condition on the SPI bus
+ * pullup CS line */
+ bGpioState |= SPI_CS;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ superio_release_configmode( iSuperIoPort );
+ return;
+}
+/**--------------------------------------------------------------------------
+ * This function generates a STOP condition on the SPI bus
+ */
+static void superio_spi_stop( void )
+{
+ superio_access_spibus();
+ /* Pull down the CS, SCK and MOSI lines */
+ bGpioState &= ~SPI_CS_SCK_MOSI;
+ superio_write_reg( iSuperIoPort, SUPERIO_GPIO_SPI_REG, bGpioState );
+ superio_release_configmode( iSuperIoPort );
+ return;
+}
+/**--------------------------------------------------------------------------
+ * This publish the functions of the SPI bus.
+ */
+SPI_INTF_FUNCTIONS SpiInterface = {
+#ifndef CONFIG_BOARD_NOKIA_IP530
+ .spi_init = superio_spi_init,
+#else
+ .spi_init = 0,
+#endif
+ .spi_start = superio_spi_start,
+ .spi_stop = superio_spi_stop,
+ .spi_wait_for_ready = superio_spi_wait_for_ready,
+ .spi_write = superio_spi_write,
+ .spi_read = superio_spi_read
+};
+/**--------------------------------------------------------------------------
+ * END
+ */
Index: src/mainboard/nokia/ip530/microchip93lc46b_spi.h
===================================================================
--- src/mainboard/nokia/ip530/microchip93lc46b_spi.h (revision 0)
+++ src/mainboard/nokia/ip530/microchip93lc46b_spi.h (revision 0)
@@ -0,0 +1,57 @@
+#ifndef __MICROCHIP_93LC46B_SPI_H__
+# define __MICROCHIP_93LC46B_SPI_H__
+# include <stdint.h>
+
+typedef enum
+{
+ SPI_CHIP_NULL_PLACEHOLDER = 0,
+# ifdef CONFIG_USES_93LC46_8BIT
+ SPI_93LC46A_WRITE_DISABLE,
+ SPI_93LC46A_WRITE_ALL,
+ SPI_93LC46A_ERASE_ALL,
+ SPI_93LC46A_WRITE_ENABLE,
+ SPI_93LC46A_WRITE,
+ SPI_93LC46A_READ,
+ SPI_93LC46A_ERASE,
+# endif
+# ifdef CONFIG_USES_93LC46_16BIT
+ SPI_93LC46B_WRITE_DISABLE,
+ SPI_93LC46B_WRITE_ALL,
+ SPI_93LC46B_ERASE_ALL,
+ SPI_93LC46B_WRITE_ENABLE,
+ SPI_93LC46B_WRITE,
+ SPI_93LC46B_READ,
+ SPI_93LC46B_ERASE,
+# endif
+ SPI_93LC46_MAX_COMMANDS,
+} SPI_93LC46_CMDS;
+
+/* Core function for the 93LC46B chip */
+uint16_t spi_93LC46_action( SPI_93LC46_CMDS eCmd, uint16_t addr, uint8_t* data );
+
+# ifdef CONFIG_USES_93LC46_8BIT
+# define spi_93LC46A_erase( addr ) spi_93LC46_action( SPI_93LC46A_ERASE, addr, '\0' )
+# define spi_93LC46A_erase_all() spi_93LC46_action( SPI_93LC46A_ERASE_ALL, 0, 0xFF )
+# define spi_93LC46A_enable_wr() spi_93LC46_action( SPI_93LC46A_WRITE_ENABLE, 0, '\0' )
+# define spi_93LC46A_disable_wr() spi_93LC46_action( SPI_93LC46A_WRITE_DISABLE, 0, '\0' )
+# define spi_93LC46A_write_word( addr, data ) spi_93LC46_action( SPI_93LC46A_WRITE, addr, data )
+# define spi_93LC46A_write_all( data ) spi_93LC46_action( SPI_93LC46A_WRITE_ALL, 0, data )
+# define spi_93LC46A_read_word( addr, data ) spi_93LC46_action( SPI_93LC46A_READ, addr, data )
+
+void spi_93LC46A_read( int address, uint8_t *bytes, uint16_t size );
+void spi_93LC46A_write( int address, uint8_t *bytes, uint16_t size );
+# endif
+
+# ifdef CONFIG_USES_93LC46_16BIT
+# define spi_93LC46B_erase( addr ) spi_93LC46_action( SPI_93LC46B_ERASE, addr, '\0' )
+# define spi_93LC46B_erase_all() spi_93LC46_action( SPI_93LC46B_ERASE_ALL, 0, (uint8_t*)"\xFF\xFF" )
+# define spi_93LC46B_enable_wr() spi_93LC46_action( SPI_93LC46B_WRITE_ENABLE, 0, '\0' )
+# define spi_93LC46B_disable_wr() spi_93LC46_action( SPI_93LC46B_WRITE_DISABLE, 0, '\0' )
+# define spi_93LC46B_write_word( addr, data ) spi_93LC46_action( SPI_93LC46B_WRITE, addr, data )
+# define spi_93LC46B_write_all( data ) spi_93LC46_action( SPI_93LC46B_WRITE_ALL, 0, data )
+# define spi_93LC46B_read_word( addr, data ) spi_93LC46_action( SPI_93LC46B_READ, addr, data )
+
+void spi_93LC46B_read( int address, uint8_t *bytes, uint16_t size );
+void spi_93LC46B_write( int address, uint8_t *bytes, uint16_t size );
+# endif
+#endif
Index: src/mainboard/nokia/ip530/superio.c
===================================================================
--- src/mainboard/nokia/ip530/superio.c (revision 0)
+++ src/mainboard/nokia/ip530/superio.c (revision 0)
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 Marc Bertens
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifdef CONFIG_BOARD_NOKIA_IP530
+/* Take the coreboot definition */
+# include <arch/io.h> // for outb(), outw(), outl(), inb(), inw() and inl()
+#else
+/* Take the Linux defintion */
+# include <sys/io.h> // for outb(), outw(), outl(), inb(), inw() and inl()
+#endif
+#include "superio.h" // For prototype check
+/****************************************************************************
+ * This is written for usage within Coreboot, but can be used outside
+ * Coreboot as well. It accesses the SPI eeprom behind the SuperIO chip.
+ * It uses the bitbang mechanism to control the SPI bus.
+ *
+ ********/
+//===========================================================================
+// Puts the superio into config mode
+//
+void superio_acquire_configmode( uint16_t port )
+{
+ /* enter_config_mode */
+ outb( 0x55, port );
+ /* In the superiotool does two writes to the port to get it in config mode */
+ outb( 0x55, port );
+ return;
+}
+//---------------------------------------------------------------------------
+// Exits the superio from config mode into normal mode.
+//
+void superio_release_configmode( uint16_t port )
+{
+ /* Exit config mode of the FDC37B878 */
+ outb( 0xAA, port );
+ return;
+}
+//---------------------------------------------------------------------------
+// Writes the data to a specific register on a specific device port address
+//
+void superio_write_reg( uint16_t port, uint8_t reg, uint8_t value )
+{
+ // Write on the control port the register to write to
+ outb( reg, port );
+ // Write on the data port the data to the register
+ outb( value, port + 1 );
+ return;
+}
+//---------------------------------------------------------------------------
+// Reads the data from a specific register on a specific device port address
+//
+uint8_t superio_read_reg( uint16_t port, uint8_t reg )
+{
+ // Write on the control port the register to read from
+ outb( reg, port );
+ // Read from the data port the data from the register
+ return ( inb( port + 1 ) );
+}
+//---------------------------------------------------------------------------
+
Index: src/mainboard/nokia/ip530/superio_spi.h
===================================================================
--- src/mainboard/nokia/ip530/superio_spi.h (revision 0)
+++ src/mainboard/nokia/ip530/superio_spi.h (revision 0)
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 Marc Bertens
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __SUPERIO_SPI_H__
+#define __SUPERIO_SPI_H__
+#include <stdint.h>
+#include <stdio.h> // for NULL
+
+/* For outside Coreboot */
+extern int iSpiHalfPeriod;
+extern uint16_t iSuperIoPort;
+
+int superio_spi_init( uint16_t port, int spi_delay );
+
+#endif
Index: src/mainboard/nokia/ip530/superio.h
===================================================================
--- src/mainboard/nokia/ip530/superio.h (revision 0)
+++ src/mainboard/nokia/ip530/superio.h (revision 0)
@@ -0,0 +1,36 @@
+#ifndef __SUPERIO_H__
+#define __SUPERIO_H__
+#include <stdint.h>
+
+#define SUPERIO_FDC37B787_ID 0x44
+#define SUPERIO_FDC37B787_REV 0x03
+
+#define SUPERIO_LDN_REG 0x07
+#define SUPERIO_LDN_GPIO 0x08
+
+#define SUPERIO_DEVICE_ID 0x20
+#define SUPERIO_DEVICE_REV 0x21
+
+#define SUPERIO_GPIO_CFG_MOSI 0xE0
+#define SUPERIO_GPIO_CFG_MISO 0xE1
+#define SUPERIO_GPIO_CFG_SCK 0xE4
+#define SUPERIO_GPIO_CFG_CS 0xE5
+#define SUPERIO_GPIO_SPI_REG 0xF6
+
+#define SUPERIO_GPIO_OUTPUT_LINE 0x00
+#define SUPERIO_GPIO_INPUT_LINE 0x01
+
+#define SPI_MOSI 0x01
+#define SPI_MISO 0x02
+#define SPI_SCK 0x10
+#define SPI_CS 0x20
+
+#define SPI_CS_SCK_MOSI 0x31
+
+void superio_acquire_configmode( uint16_t port );
+void superio_release_configmode( uint16_t port );
+
+void superio_write_reg( uint16_t port, uint8_t reg, uint8_t value );
+uint8_t superio_read_reg( uint16_t port, uint8_t reg );
+
+#endif
--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot