Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: [SPARC64]: Use alloc_pci_dev() in PCI bus probes. [SPARC64]: Bump PROMINTR_MAX to 32. [SPARC64]: Fix recursion in PROM tree building. [SERIAL] sunzilog: Interrupt enable before ISR handler installed [SPARC64] PCI: Consolidate PCI access code into pci_common.c
This commit is contained in:
Коммит
0ab598099c
|
@ -377,7 +377,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
|
||||||
const char *type;
|
const char *type;
|
||||||
u32 class;
|
u32 class;
|
||||||
|
|
||||||
dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
|
dev = alloc_pci_dev();
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,200 @@
|
||||||
#include <asm/oplib.h>
|
#include <asm/oplib.h>
|
||||||
|
|
||||||
#include "pci_impl.h"
|
#include "pci_impl.h"
|
||||||
|
#include "pci_sun4v.h"
|
||||||
|
|
||||||
|
static int config_out_of_range(struct pci_pbm_info *pbm,
|
||||||
|
unsigned long bus,
|
||||||
|
unsigned long devfn,
|
||||||
|
unsigned long reg)
|
||||||
|
{
|
||||||
|
if (bus < pbm->pci_first_busno ||
|
||||||
|
bus > pbm->pci_last_busno)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *sun4u_config_mkaddr(struct pci_pbm_info *pbm,
|
||||||
|
unsigned long bus,
|
||||||
|
unsigned long devfn,
|
||||||
|
unsigned long reg)
|
||||||
|
{
|
||||||
|
unsigned long rbits = pbm->config_space_reg_bits;
|
||||||
|
|
||||||
|
if (config_out_of_range(pbm, bus, devfn, reg))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
reg = (reg & ((1 << rbits) - 1));
|
||||||
|
devfn <<= rbits;
|
||||||
|
bus <<= rbits + 8;
|
||||||
|
|
||||||
|
return (void *) (pbm->config_space | bus | devfn | reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
||||||
|
int where, int size, u32 *value)
|
||||||
|
{
|
||||||
|
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
||||||
|
unsigned char bus = bus_dev->number;
|
||||||
|
u32 *addr;
|
||||||
|
u16 tmp16;
|
||||||
|
u8 tmp8;
|
||||||
|
|
||||||
|
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
||||||
|
return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
|
||||||
|
size, value);
|
||||||
|
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
*value = 0xff;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
*value = 0xffff;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
*value = 0xffffffff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
|
||||||
|
if (!addr)
|
||||||
|
return PCIBIOS_SUCCESSFUL;
|
||||||
|
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
pci_config_read8((u8 *)addr, &tmp8);
|
||||||
|
*value = (u32) tmp8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
if (where & 0x01) {
|
||||||
|
printk("pci_read_config_word: misaligned reg [%x]\n",
|
||||||
|
where);
|
||||||
|
return PCIBIOS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
pci_config_read16((u16 *)addr, &tmp16);
|
||||||
|
*value = (u32) tmp16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (where & 0x03) {
|
||||||
|
printk("pci_read_config_dword: misaligned reg [%x]\n",
|
||||||
|
where);
|
||||||
|
return PCIBIOS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
pci_config_read32(addr, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return PCIBIOS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
||||||
|
int where, int size, u32 value)
|
||||||
|
{
|
||||||
|
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
||||||
|
unsigned char bus = bus_dev->number;
|
||||||
|
u32 *addr;
|
||||||
|
|
||||||
|
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
||||||
|
return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
|
||||||
|
size, value);
|
||||||
|
addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
|
||||||
|
if (!addr)
|
||||||
|
return PCIBIOS_SUCCESSFUL;
|
||||||
|
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
pci_config_write8((u8 *)addr, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
if (where & 0x01) {
|
||||||
|
printk("pci_write_config_word: misaligned reg [%x]\n",
|
||||||
|
where);
|
||||||
|
return PCIBIOS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
pci_config_write16((u16 *)addr, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (where & 0x03) {
|
||||||
|
printk("pci_write_config_dword: misaligned reg [%x]\n",
|
||||||
|
where);
|
||||||
|
return PCIBIOS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
pci_config_write32(addr, value);
|
||||||
|
}
|
||||||
|
return PCIBIOS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pci_ops sun4u_pci_ops = {
|
||||||
|
.read = sun4u_read_pci_cfg,
|
||||||
|
.write = sun4u_write_pci_cfg,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
||||||
|
int where, int size, u32 *value)
|
||||||
|
{
|
||||||
|
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
||||||
|
u32 devhandle = pbm->devhandle;
|
||||||
|
unsigned int bus = bus_dev->number;
|
||||||
|
unsigned int device = PCI_SLOT(devfn);
|
||||||
|
unsigned int func = PCI_FUNC(devfn);
|
||||||
|
unsigned long ret;
|
||||||
|
|
||||||
|
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
||||||
|
return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
|
||||||
|
size, value);
|
||||||
|
if (config_out_of_range(pbm, bus, devfn, where)) {
|
||||||
|
ret = ~0UL;
|
||||||
|
} else {
|
||||||
|
ret = pci_sun4v_config_get(devhandle,
|
||||||
|
HV_PCI_DEVICE_BUILD(bus, device, func),
|
||||||
|
where, size);
|
||||||
|
}
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
*value = ret & 0xff;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
*value = ret & 0xffff;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
*value = ret & 0xffffffff;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return PCIBIOS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
||||||
|
int where, int size, u32 value)
|
||||||
|
{
|
||||||
|
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
||||||
|
u32 devhandle = pbm->devhandle;
|
||||||
|
unsigned int bus = bus_dev->number;
|
||||||
|
unsigned int device = PCI_SLOT(devfn);
|
||||||
|
unsigned int func = PCI_FUNC(devfn);
|
||||||
|
unsigned long ret;
|
||||||
|
|
||||||
|
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
||||||
|
return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
|
||||||
|
size, value);
|
||||||
|
if (config_out_of_range(pbm, bus, devfn, where)) {
|
||||||
|
/* Do nothing. */
|
||||||
|
} else {
|
||||||
|
ret = pci_sun4v_config_put(devhandle,
|
||||||
|
HV_PCI_DEVICE_BUILD(bus, device, func),
|
||||||
|
where, size, value);
|
||||||
|
}
|
||||||
|
return PCIBIOS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pci_ops sun4v_pci_ops = {
|
||||||
|
.read = sun4v_read_pci_cfg,
|
||||||
|
.write = sun4v_write_pci_cfg,
|
||||||
|
};
|
||||||
|
|
||||||
void pci_get_pbm_props(struct pci_pbm_info *pbm)
|
void pci_get_pbm_props(struct pci_pbm_info *pbm)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,138 +27,6 @@
|
||||||
"i" (ASI_PHYS_BYPASS_EC_E) \
|
"i" (ASI_PHYS_BYPASS_EC_E) \
|
||||||
: "memory")
|
: "memory")
|
||||||
|
|
||||||
/* Fire config space address format is nearly identical to
|
|
||||||
* that of SCHIZO and PSYCHO, except that in order to accomodate
|
|
||||||
* PCI-E extended config space the encoding can handle 12 bits
|
|
||||||
* of register address:
|
|
||||||
*
|
|
||||||
* 32 28 27 20 19 15 14 12 11 2 1 0
|
|
||||||
* -------------------------------------------------
|
|
||||||
* |0 0 0 0 0| bus | device | function | reg | 0 0 |
|
|
||||||
* -------------------------------------------------
|
|
||||||
*/
|
|
||||||
#define FIRE_CONFIG_BASE(PBM) ((PBM)->config_space)
|
|
||||||
#define FIRE_CONFIG_ENCODE(BUS, DEVFN, REG) \
|
|
||||||
(((unsigned long)(BUS) << 20) | \
|
|
||||||
((unsigned long)(DEVFN) << 12) | \
|
|
||||||
((unsigned long)(REG)))
|
|
||||||
|
|
||||||
static void *fire_pci_config_mkaddr(struct pci_pbm_info *pbm,
|
|
||||||
unsigned char bus,
|
|
||||||
unsigned int devfn,
|
|
||||||
int where)
|
|
||||||
{
|
|
||||||
if (!pbm)
|
|
||||||
return NULL;
|
|
||||||
return (void *)
|
|
||||||
(FIRE_CONFIG_BASE(pbm) |
|
|
||||||
FIRE_CONFIG_ENCODE(bus, devfn, where));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIRE PCI configuration space accessors. */
|
|
||||||
|
|
||||||
static int fire_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|
||||||
int where, int size, u32 *value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
|
||||||
unsigned char bus = bus_dev->number;
|
|
||||||
u32 *addr;
|
|
||||||
u16 tmp16;
|
|
||||||
u8 tmp8;
|
|
||||||
|
|
||||||
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
|
||||||
return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
|
|
||||||
size, value);
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
*value = 0xff;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*value = 0xffff;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
*value = 0xffffffff;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = fire_pci_config_mkaddr(pbm, bus, devfn, where);
|
|
||||||
if (!addr)
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
pci_config_read8((u8 *)addr, &tmp8);
|
|
||||||
*value = tmp8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
if (where & 0x01) {
|
|
||||||
printk("pci_read_config_word: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_read16((u16 *)addr, &tmp16);
|
|
||||||
*value = tmp16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
if (where & 0x03) {
|
|
||||||
printk("pci_read_config_dword: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pci_config_read32(addr, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fire_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|
||||||
int where, int size, u32 value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
|
||||||
unsigned char bus = bus_dev->number;
|
|
||||||
u32 *addr;
|
|
||||||
|
|
||||||
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
|
||||||
return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
|
|
||||||
size, value);
|
|
||||||
addr = fire_pci_config_mkaddr(pbm, bus, devfn, where);
|
|
||||||
if (!addr)
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
pci_config_write8((u8 *)addr, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
if (where & 0x01) {
|
|
||||||
printk("pci_write_config_word: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_write16((u16 *)addr, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
if (where & 0x03) {
|
|
||||||
printk("pci_write_config_dword: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pci_config_write32(addr, value);
|
|
||||||
}
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct pci_ops pci_fire_ops = {
|
|
||||||
.read = fire_read_pci_cfg,
|
|
||||||
.write = fire_write_pci_cfg,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void pci_fire_scan_bus(struct pci_pbm_info *pbm)
|
static void pci_fire_scan_bus(struct pci_pbm_info *pbm)
|
||||||
{
|
{
|
||||||
pbm->pci_bus = pci_scan_one_pbm(pbm);
|
pbm->pci_bus = pci_scan_one_pbm(pbm);
|
||||||
|
@ -314,7 +182,8 @@ static void pci_fire_pbm_init(struct pci_controller_info *p,
|
||||||
pci_pbm_root = pbm;
|
pci_pbm_root = pbm;
|
||||||
|
|
||||||
pbm->scan_bus = pci_fire_scan_bus;
|
pbm->scan_bus = pci_fire_scan_bus;
|
||||||
pbm->pci_ops = &pci_fire_ops;
|
pbm->pci_ops = &sun4u_pci_ops;
|
||||||
|
pbm->config_space_reg_bits = 12;
|
||||||
|
|
||||||
pbm->index = pci_num_pbms++;
|
pbm->index = pci_num_pbms++;
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,9 @@ struct pci_pbm_info {
|
||||||
/* Base of PCI Config space, can be per-PBM or shared. */
|
/* Base of PCI Config space, can be per-PBM or shared. */
|
||||||
unsigned long config_space;
|
unsigned long config_space;
|
||||||
|
|
||||||
|
/* This will be 12 on PCI-E controllers, 8 elsewhere. */
|
||||||
|
unsigned long config_space_reg_bits;
|
||||||
|
|
||||||
/* State of 66MHz capabilities on this PBM. */
|
/* State of 66MHz capabilities on this PBM. */
|
||||||
int is_66mhz_capable;
|
int is_66mhz_capable;
|
||||||
int all_devs_66mhz;
|
int all_devs_66mhz;
|
||||||
|
@ -156,4 +159,7 @@ extern void pci_config_write8(u8 *addr, u8 val);
|
||||||
extern void pci_config_write16(u16 *addr, u16 val);
|
extern void pci_config_write16(u16 *addr, u16 val);
|
||||||
extern void pci_config_write32(u32 *addr, u32 val);
|
extern void pci_config_write32(u32 *addr, u32 val);
|
||||||
|
|
||||||
|
extern struct pci_ops sun4u_pci_ops;
|
||||||
|
extern struct pci_ops sun4v_pci_ops;
|
||||||
|
|
||||||
#endif /* !(PCI_IMPL_H) */
|
#endif /* !(PCI_IMPL_H) */
|
||||||
|
|
|
@ -94,122 +94,6 @@ static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm,
|
||||||
PSYCHO_CONFIG_ENCODE(bus, devfn, where));
|
PSYCHO_CONFIG_ENCODE(bus, devfn, where));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int psycho_out_of_range(struct pci_pbm_info *pbm,
|
|
||||||
unsigned char bus,
|
|
||||||
unsigned char devfn)
|
|
||||||
{
|
|
||||||
return ((bus == pbm->pci_first_busno) &&
|
|
||||||
PCI_SLOT(devfn) > 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PSYCHO PCI configuration space accessors. */
|
|
||||||
|
|
||||||
static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|
||||||
int where, int size, u32 *value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
|
||||||
unsigned char bus = bus_dev->number;
|
|
||||||
u32 *addr;
|
|
||||||
u16 tmp16;
|
|
||||||
u8 tmp8;
|
|
||||||
|
|
||||||
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
|
||||||
return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
|
|
||||||
size, value);
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
*value = 0xff;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*value = 0xffff;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
*value = 0xffffffff;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
|
|
||||||
if (!addr)
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
if (psycho_out_of_range(pbm, bus, devfn))
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
pci_config_read8((u8 *)addr, &tmp8);
|
|
||||||
*value = (u32) tmp8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
if (where & 0x01) {
|
|
||||||
printk("pci_read_config_word: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_read16((u16 *)addr, &tmp16);
|
|
||||||
*value = (u32) tmp16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
if (where & 0x03) {
|
|
||||||
printk("pci_read_config_dword: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_read32(addr, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|
||||||
int where, int size, u32 value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
|
||||||
unsigned char bus = bus_dev->number;
|
|
||||||
u32 *addr;
|
|
||||||
|
|
||||||
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
|
||||||
return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
|
|
||||||
size, value);
|
|
||||||
addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
|
|
||||||
if (!addr)
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
if (psycho_out_of_range(pbm, bus, devfn))
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
pci_config_write8((u8 *)addr, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
if (where & 0x01) {
|
|
||||||
printk("pci_write_config_word: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_write16((u16 *)addr, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
if (where & 0x03) {
|
|
||||||
printk("pci_write_config_dword: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_write32(addr, value);
|
|
||||||
}
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct pci_ops psycho_ops = {
|
|
||||||
.read = psycho_read_pci_cfg,
|
|
||||||
.write = psycho_write_pci_cfg,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* PSYCHO error handling support. */
|
/* PSYCHO error handling support. */
|
||||||
enum psycho_error_type {
|
enum psycho_error_type {
|
||||||
UE_ERR, CE_ERR, PCI_ERR
|
UE_ERR, CE_ERR, PCI_ERR
|
||||||
|
@ -1089,7 +973,8 @@ static void psycho_pbm_init(struct pci_controller_info *p,
|
||||||
pci_pbm_root = pbm;
|
pci_pbm_root = pbm;
|
||||||
|
|
||||||
pbm->scan_bus = psycho_scan_bus;
|
pbm->scan_bus = psycho_scan_bus;
|
||||||
pbm->pci_ops = &psycho_ops;
|
pbm->pci_ops = &sun4u_pci_ops;
|
||||||
|
pbm->config_space_reg_bits = 8;
|
||||||
|
|
||||||
pbm->index = pci_num_pbms++;
|
pbm->index = pci_num_pbms++;
|
||||||
|
|
||||||
|
|
|
@ -205,294 +205,9 @@
|
||||||
#define SABRE_MEMSPACE 0x100000000UL
|
#define SABRE_MEMSPACE 0x100000000UL
|
||||||
#define SABRE_MEMSPACE_SIZE 0x07fffffffUL
|
#define SABRE_MEMSPACE_SIZE 0x07fffffffUL
|
||||||
|
|
||||||
/* UltraSparc-IIi Programmer's Manual, page 325, PCI
|
|
||||||
* configuration space address format:
|
|
||||||
*
|
|
||||||
* 32 24 23 16 15 11 10 8 7 2 1 0
|
|
||||||
* ---------------------------------------------------------
|
|
||||||
* |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 |
|
|
||||||
* ---------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#define SABRE_CONFIG_BASE(PBM) \
|
|
||||||
((PBM)->config_space | (1UL << 24))
|
|
||||||
#define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG) \
|
|
||||||
(((unsigned long)(BUS) << 16) | \
|
|
||||||
((unsigned long)(DEVFN) << 8) | \
|
|
||||||
((unsigned long)(REG)))
|
|
||||||
|
|
||||||
static int hummingbird_p;
|
static int hummingbird_p;
|
||||||
static struct pci_bus *sabre_root_bus;
|
static struct pci_bus *sabre_root_bus;
|
||||||
|
|
||||||
static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm,
|
|
||||||
unsigned char bus,
|
|
||||||
unsigned int devfn,
|
|
||||||
int where)
|
|
||||||
{
|
|
||||||
if (!pbm)
|
|
||||||
return NULL;
|
|
||||||
return (void *)
|
|
||||||
(SABRE_CONFIG_BASE(pbm) |
|
|
||||||
SABRE_CONFIG_ENCODE(bus, devfn, where));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sabre_out_of_range(unsigned char devfn)
|
|
||||||
{
|
|
||||||
if (hummingbird_p)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) ||
|
|
||||||
((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) ||
|
|
||||||
(PCI_SLOT(devfn) > 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __sabre_out_of_range(struct pci_pbm_info *pbm,
|
|
||||||
unsigned char bus,
|
|
||||||
unsigned char devfn)
|
|
||||||
{
|
|
||||||
if (hummingbird_p)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return ((pbm->parent == 0) ||
|
|
||||||
((pbm == &pbm->parent->pbm_A) &&
|
|
||||||
(bus == pbm->pci_first_busno) &&
|
|
||||||
PCI_SLOT(devfn) > 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|
||||||
int where, int size, u32 *value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
|
||||||
unsigned char bus = bus_dev->number;
|
|
||||||
u32 *addr;
|
|
||||||
u16 tmp16;
|
|
||||||
u8 tmp8;
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
*value = 0xff;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*value = 0xffff;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
*value = 0xffffffff;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
|
|
||||||
if (!addr)
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
if (__sabre_out_of_range(pbm, bus, devfn))
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
pci_config_read8((u8 *) addr, &tmp8);
|
|
||||||
*value = tmp8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
if (where & 0x01) {
|
|
||||||
printk("pci_read_config_word: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_read16((u16 *) addr, &tmp16);
|
|
||||||
*value = tmp16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
if (where & 0x03) {
|
|
||||||
printk("pci_read_config_dword: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_read32(addr, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn,
|
|
||||||
int where, int size, u32 *value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus->sysdata;
|
|
||||||
|
|
||||||
if (bus == pbm->pci_bus && devfn == 0x00)
|
|
||||||
return pci_host_bridge_read_pci_cfg(bus, devfn, where,
|
|
||||||
size, value);
|
|
||||||
|
|
||||||
if (!bus->number && sabre_out_of_range(devfn)) {
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
*value = 0xff;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*value = 0xffff;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
*value = 0xffffffff;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bus->number || PCI_SLOT(devfn))
|
|
||||||
return __sabre_read_pci_cfg(bus, devfn, where, size, value);
|
|
||||||
|
|
||||||
/* When accessing PCI config space of the PCI controller itself (bus
|
|
||||||
* 0, device slot 0, function 0) there are restrictions. Each
|
|
||||||
* register must be accessed as it's natural size. Thus, for example
|
|
||||||
* the Vendor ID must be accessed as a 16-bit quantity.
|
|
||||||
*/
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
if (where < 8) {
|
|
||||||
u32 tmp32;
|
|
||||||
u16 tmp16;
|
|
||||||
|
|
||||||
__sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32);
|
|
||||||
tmp16 = (u16) tmp32;
|
|
||||||
if (where & 1)
|
|
||||||
*value = tmp16 >> 8;
|
|
||||||
else
|
|
||||||
*value = tmp16 & 0xff;
|
|
||||||
} else
|
|
||||||
return __sabre_read_pci_cfg(bus, devfn, where, 1, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
if (where < 8)
|
|
||||||
return __sabre_read_pci_cfg(bus, devfn, where, 2, value);
|
|
||||||
else {
|
|
||||||
u32 tmp32;
|
|
||||||
u8 tmp8;
|
|
||||||
|
|
||||||
__sabre_read_pci_cfg(bus, devfn, where, 1, &tmp32);
|
|
||||||
tmp8 = (u8) tmp32;
|
|
||||||
*value = tmp8;
|
|
||||||
__sabre_read_pci_cfg(bus, devfn, where + 1, 1, &tmp32);
|
|
||||||
tmp8 = (u8) tmp32;
|
|
||||||
*value |= tmp8 << 8;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4: {
|
|
||||||
u32 tmp32;
|
|
||||||
u16 tmp16;
|
|
||||||
|
|
||||||
sabre_read_pci_cfg(bus, devfn, where, 2, &tmp32);
|
|
||||||
tmp16 = (u16) tmp32;
|
|
||||||
*value = tmp16;
|
|
||||||
sabre_read_pci_cfg(bus, devfn, where + 2, 2, &tmp32);
|
|
||||||
tmp16 = (u16) tmp32;
|
|
||||||
*value |= tmp16 << 16;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|
||||||
int where, int size, u32 value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
|
||||||
unsigned char bus = bus_dev->number;
|
|
||||||
u32 *addr;
|
|
||||||
|
|
||||||
addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
|
|
||||||
if (!addr)
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
if (__sabre_out_of_range(pbm, bus, devfn))
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
pci_config_write8((u8 *) addr, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
if (where & 0x01) {
|
|
||||||
printk("pci_write_config_word: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_write16((u16 *) addr, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
if (where & 0x03) {
|
|
||||||
printk("pci_write_config_dword: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_write32(addr, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn,
|
|
||||||
int where, int size, u32 value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus->sysdata;
|
|
||||||
|
|
||||||
if (bus == pbm->pci_bus && devfn == 0x00)
|
|
||||||
return pci_host_bridge_write_pci_cfg(bus, devfn, where,
|
|
||||||
size, value);
|
|
||||||
|
|
||||||
if (bus->number)
|
|
||||||
return __sabre_write_pci_cfg(bus, devfn, where, size, value);
|
|
||||||
|
|
||||||
if (sabre_out_of_range(devfn))
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
if (where < 8) {
|
|
||||||
u32 tmp32;
|
|
||||||
u16 tmp16;
|
|
||||||
|
|
||||||
__sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32);
|
|
||||||
tmp16 = (u16) tmp32;
|
|
||||||
if (where & 1) {
|
|
||||||
value &= 0x00ff;
|
|
||||||
value |= tmp16 << 8;
|
|
||||||
} else {
|
|
||||||
value &= 0xff00;
|
|
||||||
value |= tmp16;
|
|
||||||
}
|
|
||||||
tmp32 = (u32) tmp16;
|
|
||||||
return __sabre_write_pci_cfg(bus, devfn, where & ~1, 2, tmp32);
|
|
||||||
} else
|
|
||||||
return __sabre_write_pci_cfg(bus, devfn, where, 1, value);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (where < 8)
|
|
||||||
return __sabre_write_pci_cfg(bus, devfn, where, 2, value);
|
|
||||||
else {
|
|
||||||
__sabre_write_pci_cfg(bus, devfn, where, 1, value & 0xff);
|
|
||||||
__sabre_write_pci_cfg(bus, devfn, where + 1, 1, value >> 8);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
sabre_write_pci_cfg(bus, devfn, where, 2, value & 0xffff);
|
|
||||||
sabre_write_pci_cfg(bus, devfn, where + 2, 2, value >> 16);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct pci_ops sabre_ops = {
|
|
||||||
.read = sabre_read_pci_cfg,
|
|
||||||
.write = sabre_write_pci_cfg,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* SABRE error handling support. */
|
/* SABRE error handling support. */
|
||||||
static void sabre_check_iommu_error(struct pci_pbm_info *pbm,
|
static void sabre_check_iommu_error(struct pci_pbm_info *pbm,
|
||||||
unsigned long afsr,
|
unsigned long afsr,
|
||||||
|
@ -1010,7 +725,8 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct pci_pbm_info *p
|
||||||
printk("%s: SABRE PCI Bus Module\n", pbm->name);
|
printk("%s: SABRE PCI Bus Module\n", pbm->name);
|
||||||
|
|
||||||
pbm->scan_bus = sabre_scan_bus;
|
pbm->scan_bus = sabre_scan_bus;
|
||||||
pbm->pci_ops = &sabre_ops;
|
pbm->pci_ops = &sun4u_pci_ops;
|
||||||
|
pbm->config_space_reg_bits = 8;
|
||||||
|
|
||||||
pbm->index = pci_num_pbms++;
|
pbm->index = pci_num_pbms++;
|
||||||
|
|
||||||
|
|
|
@ -104,125 +104,6 @@ static void *schizo_pci_config_mkaddr(struct pci_pbm_info *pbm,
|
||||||
SCHIZO_CONFIG_ENCODE(bus, devfn, where));
|
SCHIZO_CONFIG_ENCODE(bus, devfn, where));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Just make sure the bus number is in range. */
|
|
||||||
static int schizo_out_of_range(struct pci_pbm_info *pbm,
|
|
||||||
unsigned char bus,
|
|
||||||
unsigned char devfn)
|
|
||||||
{
|
|
||||||
if (bus < pbm->pci_first_busno ||
|
|
||||||
bus > pbm->pci_last_busno)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SCHIZO PCI configuration space accessors. */
|
|
||||||
|
|
||||||
static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|
||||||
int where, int size, u32 *value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
|
||||||
unsigned char bus = bus_dev->number;
|
|
||||||
u32 *addr;
|
|
||||||
u16 tmp16;
|
|
||||||
u8 tmp8;
|
|
||||||
|
|
||||||
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
|
||||||
return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
|
|
||||||
size, value);
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
*value = 0xff;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*value = 0xffff;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
*value = 0xffffffff;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
|
|
||||||
if (!addr)
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
if (schizo_out_of_range(pbm, bus, devfn))
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
pci_config_read8((u8 *)addr, &tmp8);
|
|
||||||
*value = tmp8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
if (where & 0x01) {
|
|
||||||
printk("pci_read_config_word: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_read16((u16 *)addr, &tmp16);
|
|
||||||
*value = tmp16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
if (where & 0x03) {
|
|
||||||
printk("pci_read_config_dword: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_read32(addr, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|
||||||
int where, int size, u32 value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
|
||||||
unsigned char bus = bus_dev->number;
|
|
||||||
u32 *addr;
|
|
||||||
|
|
||||||
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
|
||||||
return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
|
|
||||||
size, value);
|
|
||||||
addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
|
|
||||||
if (!addr)
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
if (schizo_out_of_range(pbm, bus, devfn))
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
pci_config_write8((u8 *)addr, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
if (where & 0x01) {
|
|
||||||
printk("pci_write_config_word: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
pci_config_write16((u16 *)addr, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
if (where & 0x03) {
|
|
||||||
printk("pci_write_config_dword: misaligned reg [%x]\n",
|
|
||||||
where);
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pci_config_write32(addr, value);
|
|
||||||
}
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct pci_ops schizo_ops = {
|
|
||||||
.read = schizo_read_pci_cfg,
|
|
||||||
.write = schizo_write_pci_cfg,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* SCHIZO error handling support. */
|
/* SCHIZO error handling support. */
|
||||||
enum schizo_error_type {
|
enum schizo_error_type {
|
||||||
UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR
|
UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR
|
||||||
|
@ -1494,7 +1375,8 @@ static void schizo_pbm_init(struct pci_controller_info *p,
|
||||||
pci_pbm_root = pbm;
|
pci_pbm_root = pbm;
|
||||||
|
|
||||||
pbm->scan_bus = schizo_scan_bus;
|
pbm->scan_bus = schizo_scan_bus;
|
||||||
pbm->pci_ops = &schizo_ops;
|
pbm->pci_ops = &sun4u_pci_ops;
|
||||||
|
pbm->config_space_reg_bits = 8;
|
||||||
|
|
||||||
pbm->index = pci_num_pbms++;
|
pbm->index = pci_num_pbms++;
|
||||||
|
|
||||||
|
|
|
@ -593,89 +593,6 @@ const struct pci_iommu_ops pci_sun4v_iommu_ops = {
|
||||||
.dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu,
|
.dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
|
|
||||||
{
|
|
||||||
if (bus < pbm->pci_first_busno ||
|
|
||||||
bus > pbm->pci_last_busno)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|
||||||
int where, int size, u32 *value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
|
||||||
u32 devhandle = pbm->devhandle;
|
|
||||||
unsigned int bus = bus_dev->number;
|
|
||||||
unsigned int device = PCI_SLOT(devfn);
|
|
||||||
unsigned int func = PCI_FUNC(devfn);
|
|
||||||
unsigned long ret;
|
|
||||||
|
|
||||||
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
|
||||||
return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
|
|
||||||
size, value);
|
|
||||||
if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
|
|
||||||
ret = ~0UL;
|
|
||||||
} else {
|
|
||||||
ret = pci_sun4v_config_get(devhandle,
|
|
||||||
HV_PCI_DEVICE_BUILD(bus, device, func),
|
|
||||||
where, size);
|
|
||||||
#if 0
|
|
||||||
printk("rcfg: [%x:%x:%x:%d]=[%lx]\n",
|
|
||||||
devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
|
|
||||||
where, size, ret);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
*value = ret & 0xff;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*value = ret & 0xffff;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
*value = ret & 0xffffffff;
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|
||||||
int where, int size, u32 value)
|
|
||||||
{
|
|
||||||
struct pci_pbm_info *pbm = bus_dev->sysdata;
|
|
||||||
u32 devhandle = pbm->devhandle;
|
|
||||||
unsigned int bus = bus_dev->number;
|
|
||||||
unsigned int device = PCI_SLOT(devfn);
|
|
||||||
unsigned int func = PCI_FUNC(devfn);
|
|
||||||
unsigned long ret;
|
|
||||||
|
|
||||||
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
|
||||||
return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
|
|
||||||
size, value);
|
|
||||||
if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
|
|
||||||
/* Do nothing. */
|
|
||||||
} else {
|
|
||||||
ret = pci_sun4v_config_put(devhandle,
|
|
||||||
HV_PCI_DEVICE_BUILD(bus, device, func),
|
|
||||||
where, size, value);
|
|
||||||
#if 0
|
|
||||||
printk("wcfg: [%x:%x:%x:%d] v[%x] == [%lx]\n",
|
|
||||||
devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
|
|
||||||
where, size, value, ret);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return PCIBIOS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct pci_ops pci_sun4v_ops = {
|
|
||||||
.read = pci_sun4v_read_pci_cfg,
|
|
||||||
.write = pci_sun4v_write_pci_cfg,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
|
static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
|
||||||
{
|
{
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
@ -1238,7 +1155,8 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
|
||||||
pci_pbm_root = pbm;
|
pci_pbm_root = pbm;
|
||||||
|
|
||||||
pbm->scan_bus = pci_sun4v_scan_bus;
|
pbm->scan_bus = pci_sun4v_scan_bus;
|
||||||
pbm->pci_ops = &pci_sun4v_ops;
|
pbm->pci_ops = &sun4v_pci_ops;
|
||||||
|
pbm->config_space_reg_bits = 12;
|
||||||
|
|
||||||
pbm->index = pci_num_pbms++;
|
pbm->index = pci_num_pbms++;
|
||||||
|
|
||||||
|
|
|
@ -1636,10 +1636,21 @@ static struct device_node * __init create_node(phandle node, struct device_node
|
||||||
|
|
||||||
static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp)
|
static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp)
|
||||||
{
|
{
|
||||||
|
struct device_node *ret = NULL, *prev_sibling = NULL;
|
||||||
struct device_node *dp;
|
struct device_node *dp;
|
||||||
|
|
||||||
dp = create_node(node, parent);
|
while (1) {
|
||||||
if (dp) {
|
dp = create_node(node, parent);
|
||||||
|
if (!dp)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (prev_sibling)
|
||||||
|
prev_sibling->sibling = dp;
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
ret = dp;
|
||||||
|
prev_sibling = dp;
|
||||||
|
|
||||||
*(*nextp) = dp;
|
*(*nextp) = dp;
|
||||||
*nextp = &dp->allnext;
|
*nextp = &dp->allnext;
|
||||||
|
|
||||||
|
@ -1648,10 +1659,10 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl
|
||||||
|
|
||||||
dp->child = build_tree(dp, prom_getchild(node), nextp);
|
dp->child = build_tree(dp, prom_getchild(node), nextp);
|
||||||
|
|
||||||
dp->sibling = build_tree(parent, prom_getsibling(node), nextp);
|
node = prom_getsibling(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dp;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init prom_build_devicetree(void)
|
void __init prom_build_devicetree(void)
|
||||||
|
|
|
@ -92,6 +92,8 @@ struct uart_sunzilog_port {
|
||||||
#define SUNZILOG_FLAG_REGS_HELD 0x00000040
|
#define SUNZILOG_FLAG_REGS_HELD 0x00000040
|
||||||
#define SUNZILOG_FLAG_TX_STOPPED 0x00000080
|
#define SUNZILOG_FLAG_TX_STOPPED 0x00000080
|
||||||
#define SUNZILOG_FLAG_TX_ACTIVE 0x00000100
|
#define SUNZILOG_FLAG_TX_ACTIVE 0x00000100
|
||||||
|
#define SUNZILOG_FLAG_ESCC 0x00000200
|
||||||
|
#define SUNZILOG_FLAG_ISR_HANDLER 0x00000400
|
||||||
|
|
||||||
unsigned int cflag;
|
unsigned int cflag;
|
||||||
|
|
||||||
|
@ -174,9 +176,11 @@ static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel)
|
||||||
/* This function must only be called when the TX is not busy. The UART
|
/* This function must only be called when the TX is not busy. The UART
|
||||||
* port lock must be held and local interrupts disabled.
|
* port lock must be held and local interrupts disabled.
|
||||||
*/
|
*/
|
||||||
static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs)
|
static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
int escc;
|
||||||
|
unsigned char r15;
|
||||||
|
|
||||||
/* Let pending transmits finish. */
|
/* Let pending transmits finish. */
|
||||||
for (i = 0; i < 1000; i++) {
|
for (i = 0; i < 1000; i++) {
|
||||||
|
@ -229,11 +233,25 @@ static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *
|
||||||
write_zsreg(channel, R14, regs[R14]);
|
write_zsreg(channel, R14, regs[R14]);
|
||||||
|
|
||||||
/* External status interrupt control. */
|
/* External status interrupt control. */
|
||||||
write_zsreg(channel, R15, regs[R15]);
|
write_zsreg(channel, R15, (regs[R15] | WR7pEN) & ~FIFOEN);
|
||||||
|
|
||||||
|
/* ESCC Extension Register */
|
||||||
|
r15 = read_zsreg(channel, R15);
|
||||||
|
if (r15 & 0x01) {
|
||||||
|
write_zsreg(channel, R7, regs[R7p]);
|
||||||
|
|
||||||
|
/* External status interrupt and FIFO control. */
|
||||||
|
write_zsreg(channel, R15, regs[R15] & ~WR7pEN);
|
||||||
|
escc = 1;
|
||||||
|
} else {
|
||||||
|
/* Clear FIFO bit case it is an issue */
|
||||||
|
regs[R15] &= ~FIFOEN;
|
||||||
|
escc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset external status interrupts. */
|
/* Reset external status interrupts. */
|
||||||
write_zsreg(channel, R0, RES_EXT_INT);
|
write_zsreg(channel, R0, RES_EXT_INT); /* First Latch */
|
||||||
write_zsreg(channel, R0, RES_EXT_INT);
|
write_zsreg(channel, R0, RES_EXT_INT); /* Second Latch */
|
||||||
|
|
||||||
/* Rewrite R3/R5, this time without enables masked. */
|
/* Rewrite R3/R5, this time without enables masked. */
|
||||||
write_zsreg(channel, R3, regs[R3]);
|
write_zsreg(channel, R3, regs[R3]);
|
||||||
|
@ -241,6 +259,8 @@ static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *
|
||||||
|
|
||||||
/* Rewrite R1, this time without IRQ enabled masked. */
|
/* Rewrite R1, this time without IRQ enabled masked. */
|
||||||
write_zsreg(channel, R1, regs[R1]);
|
write_zsreg(channel, R1, regs[R1]);
|
||||||
|
|
||||||
|
return escc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reprogram the Zilog channel HW registers with the copies found in the
|
/* Reprogram the Zilog channel HW registers with the copies found in the
|
||||||
|
@ -731,7 +751,7 @@ static void sunzilog_enable_ms(struct uart_port *port)
|
||||||
up->curregs[R15] = new_reg;
|
up->curregs[R15] = new_reg;
|
||||||
|
|
||||||
/* NOTE: Not subject to 'transmitter active' rule. */
|
/* NOTE: Not subject to 'transmitter active' rule. */
|
||||||
write_zsreg(channel, R15, up->curregs[R15]);
|
write_zsreg(channel, R15, up->curregs[R15] & ~WR7pEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,44 +881,44 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag,
|
||||||
up->curregs[R14] = BRSRC | BRENAB;
|
up->curregs[R14] = BRSRC | BRENAB;
|
||||||
|
|
||||||
/* Character size, stop bits, and parity. */
|
/* Character size, stop bits, and parity. */
|
||||||
up->curregs[3] &= ~RxN_MASK;
|
up->curregs[R3] &= ~RxN_MASK;
|
||||||
up->curregs[5] &= ~TxN_MASK;
|
up->curregs[R5] &= ~TxN_MASK;
|
||||||
switch (cflag & CSIZE) {
|
switch (cflag & CSIZE) {
|
||||||
case CS5:
|
case CS5:
|
||||||
up->curregs[3] |= Rx5;
|
up->curregs[R3] |= Rx5;
|
||||||
up->curregs[5] |= Tx5;
|
up->curregs[R5] |= Tx5;
|
||||||
up->parity_mask = 0x1f;
|
up->parity_mask = 0x1f;
|
||||||
break;
|
break;
|
||||||
case CS6:
|
case CS6:
|
||||||
up->curregs[3] |= Rx6;
|
up->curregs[R3] |= Rx6;
|
||||||
up->curregs[5] |= Tx6;
|
up->curregs[R5] |= Tx6;
|
||||||
up->parity_mask = 0x3f;
|
up->parity_mask = 0x3f;
|
||||||
break;
|
break;
|
||||||
case CS7:
|
case CS7:
|
||||||
up->curregs[3] |= Rx7;
|
up->curregs[R3] |= Rx7;
|
||||||
up->curregs[5] |= Tx7;
|
up->curregs[R5] |= Tx7;
|
||||||
up->parity_mask = 0x7f;
|
up->parity_mask = 0x7f;
|
||||||
break;
|
break;
|
||||||
case CS8:
|
case CS8:
|
||||||
default:
|
default:
|
||||||
up->curregs[3] |= Rx8;
|
up->curregs[R3] |= Rx8;
|
||||||
up->curregs[5] |= Tx8;
|
up->curregs[R5] |= Tx8;
|
||||||
up->parity_mask = 0xff;
|
up->parity_mask = 0xff;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
up->curregs[4] &= ~0x0c;
|
up->curregs[R4] &= ~0x0c;
|
||||||
if (cflag & CSTOPB)
|
if (cflag & CSTOPB)
|
||||||
up->curregs[4] |= SB2;
|
up->curregs[R4] |= SB2;
|
||||||
else
|
else
|
||||||
up->curregs[4] |= SB1;
|
up->curregs[R4] |= SB1;
|
||||||
if (cflag & PARENB)
|
if (cflag & PARENB)
|
||||||
up->curregs[4] |= PAR_ENAB;
|
up->curregs[R4] |= PAR_ENAB;
|
||||||
else
|
else
|
||||||
up->curregs[4] &= ~PAR_ENAB;
|
up->curregs[R4] &= ~PAR_ENAB;
|
||||||
if (!(cflag & PARODD))
|
if (!(cflag & PARODD))
|
||||||
up->curregs[4] |= PAR_EVEN;
|
up->curregs[R4] |= PAR_EVEN;
|
||||||
else
|
else
|
||||||
up->curregs[4] &= ~PAR_EVEN;
|
up->curregs[R4] &= ~PAR_EVEN;
|
||||||
|
|
||||||
up->port.read_status_mask = Rx_OVR;
|
up->port.read_status_mask = Rx_OVR;
|
||||||
if (iflag & INPCK)
|
if (iflag & INPCK)
|
||||||
|
@ -952,7 +972,9 @@ sunzilog_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
|
|
||||||
static const char *sunzilog_type(struct uart_port *port)
|
static const char *sunzilog_type(struct uart_port *port)
|
||||||
{
|
{
|
||||||
return "zs";
|
struct uart_sunzilog_port *up = UART_ZILOG(port);
|
||||||
|
|
||||||
|
return (up->flags & SUNZILOG_FLAG_ESCC) ? "zs (ESCC)" : "zs";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We do not request/release mappings of the registers here, this
|
/* We do not request/release mappings of the registers here, this
|
||||||
|
@ -1170,7 +1192,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options)
|
||||||
|
|
||||||
spin_lock_irqsave(&up->port.lock, flags);
|
spin_lock_irqsave(&up->port.lock, flags);
|
||||||
|
|
||||||
up->curregs[R15] = BRKIE;
|
up->curregs[R15] |= BRKIE;
|
||||||
sunzilog_convert_to_zs(up, con->cflag, 0, brg);
|
sunzilog_convert_to_zs(up, con->cflag, 0, brg);
|
||||||
|
|
||||||
sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
|
sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
|
||||||
|
@ -1229,7 +1251,7 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
|
||||||
baud = 4800;
|
baud = 4800;
|
||||||
}
|
}
|
||||||
|
|
||||||
up->curregs[R15] = BRKIE;
|
up->curregs[R15] |= BRKIE;
|
||||||
brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
|
brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
|
||||||
sunzilog_convert_to_zs(up, up->cflag, 0, brg);
|
sunzilog_convert_to_zs(up, up->cflag, 0, brg);
|
||||||
sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
|
sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
|
||||||
|
@ -1283,8 +1305,18 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
|
||||||
|
|
||||||
if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
|
if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
|
||||||
SUNZILOG_FLAG_CONS_MOUSE)) {
|
SUNZILOG_FLAG_CONS_MOUSE)) {
|
||||||
|
up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
|
||||||
|
up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
|
||||||
|
up->curregs[R3] = RxENAB | Rx8;
|
||||||
|
up->curregs[R5] = TxENAB | Tx8;
|
||||||
|
up->curregs[R6] = 0x00; /* SDLC Address */
|
||||||
|
up->curregs[R7] = 0x7E; /* SDLC Flag */
|
||||||
|
up->curregs[R9] = NV;
|
||||||
|
up->curregs[R7p] = 0x00;
|
||||||
sunzilog_init_kbdms(up, up->port.line);
|
sunzilog_init_kbdms(up, up->port.line);
|
||||||
up->curregs[R9] |= (NV | MIE);
|
/* Only enable interrupts if an ISR handler available */
|
||||||
|
if (up->flags & SUNZILOG_FLAG_ISR_HANDLER)
|
||||||
|
up->curregs[R9] |= MIE;
|
||||||
write_zsreg(channel, R9, up->curregs[R9]);
|
write_zsreg(channel, R9, up->curregs[R9]);
|
||||||
} else {
|
} else {
|
||||||
/* Normal serial TTY. */
|
/* Normal serial TTY. */
|
||||||
|
@ -1293,7 +1325,9 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
|
||||||
up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
|
up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
|
||||||
up->curregs[R3] = RxENAB | Rx8;
|
up->curregs[R3] = RxENAB | Rx8;
|
||||||
up->curregs[R5] = TxENAB | Tx8;
|
up->curregs[R5] = TxENAB | Tx8;
|
||||||
up->curregs[R9] = NV | MIE;
|
up->curregs[R6] = 0x00; /* SDLC Address */
|
||||||
|
up->curregs[R7] = 0x7E; /* SDLC Flag */
|
||||||
|
up->curregs[R9] = NV;
|
||||||
up->curregs[R10] = NRZ;
|
up->curregs[R10] = NRZ;
|
||||||
up->curregs[R11] = TCBR | RCBR;
|
up->curregs[R11] = TCBR | RCBR;
|
||||||
baud = 9600;
|
baud = 9600;
|
||||||
|
@ -1301,7 +1335,14 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
|
||||||
up->curregs[R12] = (brg & 0xff);
|
up->curregs[R12] = (brg & 0xff);
|
||||||
up->curregs[R13] = (brg >> 8) & 0xff;
|
up->curregs[R13] = (brg >> 8) & 0xff;
|
||||||
up->curregs[R14] = BRSRC | BRENAB;
|
up->curregs[R14] = BRSRC | BRENAB;
|
||||||
__load_zsregs(channel, up->curregs);
|
up->curregs[R15] = FIFOEN; /* Use FIFO if on ESCC */
|
||||||
|
up->curregs[R7p] = TxFIFO_LVL | RxFIFO_LVL;
|
||||||
|
if (__load_zsregs(channel, up->curregs)) {
|
||||||
|
up->flags |= SUNZILOG_FLAG_ESCC;
|
||||||
|
}
|
||||||
|
/* Only enable interrupts if an ISR handler available */
|
||||||
|
if (up->flags & SUNZILOG_FLAG_ISR_HANDLER)
|
||||||
|
up->curregs[R9] |= MIE;
|
||||||
write_zsreg(channel, R9, up->curregs[R9]);
|
write_zsreg(channel, R9, up->curregs[R9]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1390,12 +1431,14 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_INFO "%s: Keyboard at MMIO %lx (irq = %d) "
|
printk(KERN_INFO "%s: Keyboard at MMIO 0x%lx (irq = %d) "
|
||||||
"is a zs\n",
|
"is a %s\n",
|
||||||
op->dev.bus_id, up[0].port.mapbase, op->irqs[0]);
|
op->dev.bus_id, up[0].port.mapbase, op->irqs[0],
|
||||||
printk(KERN_INFO "%s: Mouse at MMIO %lx (irq = %d) "
|
sunzilog_type (&up[0].port));
|
||||||
"is a zs\n",
|
printk(KERN_INFO "%s: Mouse at MMIO 0x%lx (irq = %d) "
|
||||||
op->dev.bus_id, up[1].port.mapbase, op->irqs[0]);
|
"is a %s\n",
|
||||||
|
op->dev.bus_id, up[1].port.mapbase, op->irqs[0],
|
||||||
|
sunzilog_type (&up[1].port));
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_set_drvdata(&op->dev, &up[0]);
|
dev_set_drvdata(&op->dev, &up[0]);
|
||||||
|
@ -1487,10 +1530,23 @@ static int __init sunzilog_init(void)
|
||||||
goto out_unregister_uart;
|
goto out_unregister_uart;
|
||||||
|
|
||||||
if (zilog_irq != -1) {
|
if (zilog_irq != -1) {
|
||||||
|
struct uart_sunzilog_port *up = sunzilog_irq_chain;
|
||||||
err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
|
err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
|
||||||
"zs", sunzilog_irq_chain);
|
"zs", sunzilog_irq_chain);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unregister_driver;
|
goto out_unregister_driver;
|
||||||
|
|
||||||
|
/* Enable Interrupts */
|
||||||
|
while (up) {
|
||||||
|
struct zilog_channel __iomem *channel;
|
||||||
|
|
||||||
|
/* printk (KERN_INFO "Enable IRQ for ZILOG Hardware %p\n", up); */
|
||||||
|
channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
|
||||||
|
up->flags |= SUNZILOG_FLAG_ISR_HANDLER;
|
||||||
|
up->curregs[R9] |= MIE;
|
||||||
|
write_zsreg(channel, R9, up->curregs[R9]);
|
||||||
|
up = up->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -1515,6 +1571,20 @@ static void __exit sunzilog_exit(void)
|
||||||
of_unregister_driver(&zs_driver);
|
of_unregister_driver(&zs_driver);
|
||||||
|
|
||||||
if (zilog_irq != -1) {
|
if (zilog_irq != -1) {
|
||||||
|
struct uart_sunzilog_port *up = sunzilog_irq_chain;
|
||||||
|
|
||||||
|
/* Disable Interrupts */
|
||||||
|
while (up) {
|
||||||
|
struct zilog_channel __iomem *channel;
|
||||||
|
|
||||||
|
/* printk (KERN_INFO "Disable IRQ for ZILOG Hardware %p\n", up); */
|
||||||
|
channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
|
||||||
|
up->flags &= ~SUNZILOG_FLAG_ISR_HANDLER;
|
||||||
|
up->curregs[R9] &= ~MIE;
|
||||||
|
write_zsreg(channel, R9, up->curregs[R9]);
|
||||||
|
up = up->next;
|
||||||
|
}
|
||||||
|
|
||||||
free_irq(zilog_irq, sunzilog_irq_chain);
|
free_irq(zilog_irq, sunzilog_irq_chain);
|
||||||
zilog_irq = -1;
|
zilog_irq = -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ struct zilog_layout {
|
||||||
struct zilog_channel channelA;
|
struct zilog_channel channelA;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_ZSREGS 16
|
#define NUM_ZSREGS 17
|
||||||
|
#define R7p 16 /* Written as R7 with P15 bit 0 set */
|
||||||
|
|
||||||
/* Conversion routines to/from brg time constants from/to bits
|
/* Conversion routines to/from brg time constants from/to bits
|
||||||
* per second.
|
* per second.
|
||||||
|
@ -127,6 +128,15 @@ struct zilog_layout {
|
||||||
|
|
||||||
/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
|
/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
|
||||||
|
|
||||||
|
/* Write Register 7' (ESCC Only) */
|
||||||
|
#define AUTO_TxFLAG 1 /* Automatic Tx SDLC Flag */
|
||||||
|
#define AUTO_EOM_RST 2 /* Automatic EOM Reset */
|
||||||
|
#define AUTOnRTS 4 /* Automatic /RTS pin deactivation */
|
||||||
|
#define RxFIFO_LVL 8 /* Receive FIFO interrupt level */
|
||||||
|
#define nDTRnREQ 0x10 /* /DTR/REQ timing */
|
||||||
|
#define TxFIFO_LVL 0x20 /* Transmit FIFO interrupt level */
|
||||||
|
#define EXT_RD_EN 0x40 /* Extended read register enable */
|
||||||
|
|
||||||
/* Write Register 8 (transmit buffer) */
|
/* Write Register 8 (transmit buffer) */
|
||||||
|
|
||||||
/* Write Register 9 (Master interrupt control) */
|
/* Write Register 9 (Master interrupt control) */
|
||||||
|
@ -135,6 +145,7 @@ struct zilog_layout {
|
||||||
#define DLC 4 /* Disable Lower Chain */
|
#define DLC 4 /* Disable Lower Chain */
|
||||||
#define MIE 8 /* Master Interrupt Enable */
|
#define MIE 8 /* Master Interrupt Enable */
|
||||||
#define STATHI 0x10 /* Status high */
|
#define STATHI 0x10 /* Status high */
|
||||||
|
#define SWIACK 0x20 /* Software Interrupt Ack (not on NMOS) */
|
||||||
#define NORESET 0 /* No reset on write to R9 */
|
#define NORESET 0 /* No reset on write to R9 */
|
||||||
#define CHRB 0x40 /* Reset channel B */
|
#define CHRB 0x40 /* Reset channel B */
|
||||||
#define CHRA 0x80 /* Reset channel A */
|
#define CHRA 0x80 /* Reset channel A */
|
||||||
|
@ -187,7 +198,9 @@ struct zilog_layout {
|
||||||
#define SNRZI 0xe0 /* Set NRZI mode */
|
#define SNRZI 0xe0 /* Set NRZI mode */
|
||||||
|
|
||||||
/* Write Register 15 (external/status interrupt control) */
|
/* Write Register 15 (external/status interrupt control) */
|
||||||
|
#define WR7pEN 1 /* WR7' Enable (ESCC only) */
|
||||||
#define ZCIE 2 /* Zero count IE */
|
#define ZCIE 2 /* Zero count IE */
|
||||||
|
#define FIFOEN 4 /* FIFO Enable (ESCC only) */
|
||||||
#define DCDIE 8 /* DCD IE */
|
#define DCDIE 8 /* DCD IE */
|
||||||
#define SYNCIE 0x10 /* Sync/hunt IE */
|
#define SYNCIE 0x10 /* Sync/hunt IE */
|
||||||
#define CTSIE 0x20 /* CTS IE */
|
#define CTSIE 0x20 /* CTS IE */
|
||||||
|
@ -241,6 +254,10 @@ struct zilog_layout {
|
||||||
#define CHATxIP 0x10 /* Channel A Tx IP */
|
#define CHATxIP 0x10 /* Channel A Tx IP */
|
||||||
#define CHARxIP 0x20 /* Channel A Rx IP */
|
#define CHARxIP 0x20 /* Channel A Rx IP */
|
||||||
|
|
||||||
|
/* Read Register 6 (LSB frame byte count [Not on NMOS]) */
|
||||||
|
|
||||||
|
/* Read Register 7 (MSB frame byte count and FIFO status [Not on NMOS]) */
|
||||||
|
|
||||||
/* Read Register 8 (receive data register) */
|
/* Read Register 8 (receive data register) */
|
||||||
|
|
||||||
/* Read Register 10 (misc status bits) */
|
/* Read Register 10 (misc status bits) */
|
||||||
|
|
|
@ -177,7 +177,7 @@ struct linux_nodeops {
|
||||||
/* More fun PROM structures for device probing. */
|
/* More fun PROM structures for device probing. */
|
||||||
#define PROMREG_MAX 24
|
#define PROMREG_MAX 24
|
||||||
#define PROMVADDR_MAX 16
|
#define PROMVADDR_MAX 16
|
||||||
#define PROMINTR_MAX 15
|
#define PROMINTR_MAX 32
|
||||||
|
|
||||||
struct linux_prom_registers {
|
struct linux_prom_registers {
|
||||||
unsigned which_io; /* hi part of physical address */
|
unsigned which_io; /* hi part of physical address */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче