From: Henrik Brix Andersen <brix@gentoo.org>
To: Linus Torvalds <torvalds@osdl.org>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] Resend: Determine SCx200 CB address at run-time
Date: Wed, 02 Mar 2005 19:12:37 +0100 [thread overview]
Message-ID: <1109787158.12086.11.camel@sponge.fungus> (raw)
[-- Attachment #1: Type: text/plain, Size: 12274 bytes --]
The current SCx200 drivers use a fixed base address of 0x9000 for the
Configuration Block, but some systems (at least the Soekris net4801)
uses a base address of 0x6000. This patch first tries the fixed address
then - if no configuration block could be found - tries the address
written to the Configuration Block Address Scratchpad register by the
BIOS.
This was first sent at Wed, 23 Feb 2005 13:53:33 +0100.
Signed-off-by: Henrik Brix Andersen <brix@gentoo.org>
---
diff -urp linux-2.6.11/arch/i386/kernel/scx200.c linux-2.6.11-scx200/arch/i386/kernel/scx200.c
--- linux-2.6.11/arch/i386/kernel/scx200.c 2005-03-02 08:38:25.000000000 +0100
+++ linux-2.6.11-scx200/arch/i386/kernel/scx200.c 2005-03-02 18:01:56.000000000 +0100
@@ -13,6 +13,9 @@
#include <linux/scx200.h>
+/* Verify that the configuration block really is there */
+#define scx200_cb_probe(base) (inw((base) + SCx200_CBA) == (base))
+
#define NAME "scx200"
MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
@@ -22,9 +25,13 @@ MODULE_LICENSE("GPL");
unsigned scx200_gpio_base = 0;
long scx200_gpio_shadow[2];
+unsigned scx200_cb_base = 0;
+
static struct pci_device_id scx200_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_XBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_XBUS) },
{ },
};
MODULE_DEVICE_TABLE(pci,scx200_tbl);
@@ -45,22 +52,39 @@ static int __devinit scx200_probe(struct
int bank;
unsigned base;
- base = pci_resource_start(pdev, 0);
- printk(KERN_INFO NAME ": GPIO base 0x%x\n", base);
-
- if (request_region(base, SCx200_GPIO_SIZE, "NatSemi SCx200 GPIO") == 0) {
- printk(KERN_ERR NAME ": can't allocate I/O for GPIOs\n");
- return -EBUSY;
+ if (pdev->device == PCI_DEVICE_ID_NS_SCx200_BRIDGE ||
+ pdev->device == PCI_DEVICE_ID_NS_SC1100_BRIDGE) {
+ base = pci_resource_start(pdev, 0);
+ printk(KERN_INFO NAME ": GPIO base 0x%x\n", base);
+
+ if (request_region(base, SCx200_GPIO_SIZE, "NatSemi SCx200 GPIO") == 0) {
+ printk(KERN_ERR NAME ": can't allocate I/O for GPIOs\n");
+ return -EBUSY;
+ }
+
+ scx200_gpio_base = base;
+
+ /* read the current values driven on the GPIO signals */
+ for (bank = 0; bank < 2; ++bank)
+ scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank);
+
+ } else {
+ /* find the base of the Configuration Block */
+ if (scx200_cb_probe(SCx200_CB_BASE_FIXED)) {
+ scx200_cb_base = SCx200_CB_BASE_FIXED;
+ } else {
+ pci_read_config_dword(pdev, SCx200_CBA_SCRATCH, &base);
+ if (scx200_cb_probe(base)) {
+ scx200_cb_base = base;
+ } else {
+ printk(KERN_WARNING NAME ": Configuration Block not found\n");
+ return -ENODEV;
+ }
+ }
+ printk(KERN_INFO NAME ": Configuration Block base 0x%x\n", scx200_cb_base);
}
- scx200_gpio_base = base;
-
- /* read the current values driven on the GPIO signals */
- for (bank = 0; bank < 2; ++bank)
- scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank);
-
return 0;
-
}
u32 scx200_gpio_configure(int index, u32 mask, u32 bits)
@@ -134,6 +158,7 @@ EXPORT_SYMBOL(scx200_gpio_shadow);
EXPORT_SYMBOL(scx200_gpio_lock);
EXPORT_SYMBOL(scx200_gpio_configure);
EXPORT_SYMBOL(scx200_gpio_dump);
+EXPORT_SYMBOL(scx200_cb_base);
/*
Local variables:
diff -urp linux-2.6.11/drivers/char/watchdog/Kconfig linux-2.6.11-scx200/drivers/char/watchdog/Kconfig
--- linux-2.6.11/drivers/char/watchdog/Kconfig 2005-03-02 08:38:13.000000000 +0100
+++ linux-2.6.11-scx200/drivers/char/watchdog/Kconfig 2005-03-02 18:01:56.000000000 +0100
@@ -268,12 +268,12 @@ config SC1200_WDT
config SCx200_WDT
tristate "National Semiconductor SCx200 Watchdog"
- depends on WATCHDOG && X86 && PCI
+ depends on WATCHDOG && SCx200 && PCI
help
Enable the built-in watchdog timer support on the National
Semiconductor SCx200 processors.
- If compiled as a module, it will be called scx200_watchdog.
+ If compiled as a module, it will be called scx200_wdt.
config 60XX_WDT
tristate "SBC-60XX Watchdog Timer"
diff -urp linux-2.6.11/drivers/char/watchdog/scx200_wdt.c linux-2.6.11-scx200/drivers/char/watchdog/scx200_wdt.c
--- linux-2.6.11/drivers/char/watchdog/scx200_wdt.c 2005-03-02 08:38:13.000000000 +0100
+++ linux-2.6.11-scx200/drivers/char/watchdog/scx200_wdt.c 2005-03-02 18:01:56.000000000 +0100
@@ -64,7 +64,7 @@ static char expect_close;
static void scx200_wdt_ping(void)
{
- outw(wdto_restart, SCx200_CB_BASE + SCx200_WDT_WDTO);
+ outw(wdto_restart, scx200_cb_base + SCx200_WDT_WDTO);
}
static void scx200_wdt_update_margin(void)
@@ -78,9 +78,9 @@ static void scx200_wdt_enable(void)
printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n",
wdto_restart);
- outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO);
- outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS);
- outw(W_ENABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG);
+ outw(0, scx200_cb_base + SCx200_WDT_WDTO);
+ outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
+ outw(W_ENABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
scx200_wdt_ping();
}
@@ -89,9 +89,9 @@ static void scx200_wdt_disable(void)
{
printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
- outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO);
- outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS);
- outw(W_DISABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG);
+ outw(0, scx200_cb_base + SCx200_WDT_WDTO);
+ outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
+ outw(W_DISABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
}
static int scx200_wdt_open(struct inode *inode, struct file *file)
@@ -210,35 +210,21 @@ static struct file_operations scx200_wdt
static struct miscdevice scx200_wdt_miscdev = {
.minor = WATCHDOG_MINOR,
- .name = NAME,
+ .name = "watchdog",
.fops = &scx200_wdt_fops,
};
static int __init scx200_wdt_init(void)
{
int r;
- static struct pci_device_id ns_sc[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
- { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
- { },
- };
printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n");
- /*
- * First check that this really is a NatSemi SCx200 CPU or a Geode
- * SC1100 processor
- */
- if (!pci_dev_present(ns_sc))
- return -ENODEV;
-
- /* More sanity checks, verify that the configuration block is there */
- if (!scx200_cb_probe(SCx200_CB_BASE)) {
- printk(KERN_WARNING NAME ": no configuration block found\n");
+ /* check that we have found the configuration block */
+ if (!scx200_cb_present())
return -ENODEV;
- }
- if (!request_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+ if (!request_region(scx200_cb_base + SCx200_WDT_OFFSET,
SCx200_WDT_SIZE,
"NatSemi SCx200 Watchdog")) {
printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
@@ -252,7 +238,7 @@ static int __init scx200_wdt_init(void)
r = misc_register(&scx200_wdt_miscdev);
if (r) {
- release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+ release_region(scx200_cb_base + SCx200_WDT_OFFSET,
SCx200_WDT_SIZE);
return r;
}
@@ -261,7 +247,7 @@ static int __init scx200_wdt_init(void)
if (r) {
printk(KERN_ERR NAME ": unable to register reboot notifier");
misc_deregister(&scx200_wdt_miscdev);
- release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+ release_region(scx200_cb_base + SCx200_WDT_OFFSET,
SCx200_WDT_SIZE);
return r;
}
@@ -273,7 +259,7 @@ static void __exit scx200_wdt_cleanup(vo
{
unregister_reboot_notifier(&scx200_wdt_notifier);
misc_deregister(&scx200_wdt_miscdev);
- release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+ release_region(scx200_cb_base + SCx200_WDT_OFFSET,
SCx200_WDT_SIZE);
}
diff -urp linux-2.6.11/drivers/mtd/maps/Kconfig linux-2.6.11-scx200/drivers/mtd/maps/Kconfig
--- linux-2.6.11/drivers/mtd/maps/Kconfig 2005-03-02 08:38:32.000000000 +0100
+++ linux-2.6.11-scx200/drivers/mtd/maps/Kconfig 2005-03-02 18:01:56.000000000 +0100
@@ -159,7 +159,7 @@ config MTD_VMAX
config MTD_SCx200_DOCFLASH
tristate "Flash device mapped with DOCCS on NatSemi SCx200"
- depends on X86 && MTD_CFI && MTD_PARTITIONS
+ depends on SCx200 && MTD_CFI && MTD_PARTITIONS
help
Enable support for a flash chip mapped using the DOCCS signal on a
National Semiconductor SCx200 processor.
diff -urp linux-2.6.11/drivers/mtd/maps/scx200_docflash.c linux-2.6.11-scx200/drivers/mtd/maps/scx200_docflash.c
--- linux-2.6.11/drivers/mtd/maps/scx200_docflash.c 2005-03-02 08:38:13.000000000 +0100
+++ linux-2.6.11-scx200/drivers/mtd/maps/scx200_docflash.c 2005-03-02 18:01:56.000000000 +0100
@@ -92,17 +92,16 @@ static int __init init_scx200_docflash(v
PCI_DEVICE_ID_NS_SCx200_BRIDGE,
NULL)) == NULL)
return -ENODEV;
-
- if (!scx200_cb_probe(SCx200_CB_BASE)) {
- printk(KERN_WARNING NAME ": no configuration block found\n");
+
+ /* check that we have found the configuration block */
+ if (!scx200_cb_present())
return -ENODEV;
- }
if (probe) {
/* Try to use the present flash mapping if any */
pci_read_config_dword(bridge, SCx200_DOCCS_BASE, &base);
pci_read_config_dword(bridge, SCx200_DOCCS_CTRL, &ctrl);
- pmr = inl(SCx200_CB_BASE + SCx200_PMR);
+ pmr = inl(scx200_cb_base + SCx200_PMR);
if (base == 0
|| (ctrl & 0x07000000) != 0x07000000
@@ -155,14 +154,14 @@ static int __init init_scx200_docflash(v
pci_write_config_dword(bridge, SCx200_DOCCS_BASE, docmem.start);
pci_write_config_dword(bridge, SCx200_DOCCS_CTRL, ctrl);
- pmr = inl(SCx200_CB_BASE + SCx200_PMR);
+ pmr = inl(scx200_cb_base + SCx200_PMR);
if (width == 8) {
pmr &= ~(1<<6);
} else {
pmr |= (1<<6);
}
- outl(pmr, SCx200_CB_BASE + SCx200_PMR);
+ outl(pmr, scx200_cb_base + SCx200_PMR);
}
printk(KERN_INFO NAME ": DOCCS mapped at 0x%lx-0x%lx, width %d\n",
diff -urp linux-2.6.11/include/linux/pci_ids.h linux-2.6.11-scx200/include/linux/pci_ids.h
--- linux-2.6.11/include/linux/pci_ids.h 2005-03-02 08:38:37.000000000 +0100
+++ linux-2.6.11-scx200/include/linux/pci_ids.h 2005-03-02 18:01:56.000000000 +0100
@@ -386,6 +386,8 @@
#define PCI_DEVICE_ID_NS_SCx200_VIDEO 0x0504
#define PCI_DEVICE_ID_NS_SCx200_XBUS 0x0505
#define PCI_DEVICE_ID_NS_SC1100_BRIDGE 0x0510
+#define PCI_DEVICE_ID_NS_SC1100_SMI 0x0511
+#define PCI_DEVICE_ID_NS_SC1100_XBUS 0x0515
#define PCI_DEVICE_ID_NS_87410 0xd001
#define PCI_VENDOR_ID_TSENG 0x100c
diff -urp linux-2.6.11/include/linux/scx200.h linux-2.6.11-scx200/include/linux/scx200.h
--- linux-2.6.11/include/linux/scx200.h 2005-03-02 08:38:13.000000000 +0100
+++ linux-2.6.11-scx200/include/linux/scx200.h 2005-03-02 18:01:56.000000000 +0100
@@ -7,6 +7,10 @@
/* Interesting stuff for the National Semiconductor SCx200 CPU */
+extern unsigned scx200_cb_base;
+
+#define scx200_cb_present() (scx200_cb_base!=0)
+
/* F0 PCI Header/Bridge Configuration Registers */
#define SCx200_DOCCS_BASE 0x78 /* DOCCS Base Address Register */
#define SCx200_DOCCS_CTRL 0x7c /* DOCCS Control Register */
@@ -15,7 +19,7 @@
#define SCx200_GPIO_SIZE 0x2c /* Size of GPIO register block */
/* General Configuration Block */
-#define SCx200_CB_BASE 0x9000 /* Base fixed at 0x9000 according to errata */
+#define SCx200_CB_BASE_FIXED 0x9000 /* Base fixed at 0x9000 according to errata? */
/* Watchdog Timer */
#define SCx200_WDT_OFFSET 0x00 /* offset within configuration block */
@@ -44,9 +48,7 @@
#define SCx200_IID 0x3c /* IA On a Chip Identification Number Reg */
#define SCx200_REV 0x3d /* Revision Register */
#define SCx200_CBA 0x3e /* Configuration Base Address Register */
-
-/* Verify that the configuration block really is there */
-#define scx200_cb_probe(base) (inw((base) + SCx200_CBA) == (base))
+#define SCx200_CBA_SCRATCH 0x64 /* Configuration Base Address Scratchpad */
/*
Local variables:
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
next reply other threads:[~2005-03-02 18:17 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-03-02 18:12 Henrik Brix Andersen [this message]
2005-03-02 18:29 ` [PATCH] Resend: Determine SCx200 CB address at run-time Henrik Brix Andersen
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=1109787158.12086.11.camel@sponge.fungus \
--to=brix@gentoo.org \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@osdl.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.