Commit 5ec72d2e authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Russell King

[PCMCIA] unify yenta.c and pci_socket.c

Linus said [on April 25th of this year]:
> There are two reasons I did pci_socket, and one of them is stale
> and the other one is a matter of taste.

As the second reason is stale now, too, unify yenta.c and
pci_socket.c.
parent 7e5ca9e1
......@@ -29,8 +29,8 @@ config PCMCIA
and ds. If you want to compile it as a module, say M here and
read <file:Documentation/modules.txt>.
config CARDBUS
bool "CardBus support"
config YENTA
tristate "CardBus yenta-compatible bridge support"
depends on PCMCIA && PCI
---help---
CardBus is a bus mastering architecture for PC-cards, which allows
......@@ -48,6 +48,11 @@ config CARDBUS
If unsure, say Y.
config CARDBUS
bool
depends on YENTA
default y if YENTA
config I82092
tristate "i82092 compatible bridge support"
depends on PCMCIA && PCI
......
......@@ -3,9 +3,7 @@
#
obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o
ifeq ($(CONFIG_CARDBUS),y)
obj-$(CONFIG_PCMCIA) += yenta_socket.o
endif
obj-$(CONFIG_YENTA) += yenta.o
obj-$(CONFIG_I82365) += i82365.o
obj-$(CONFIG_I82092) += i82092.o
......@@ -14,8 +12,6 @@ obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o
obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o
obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o
yenta_socket-y += pci_socket.o yenta.o
pcmcia_core-y += cistpl.o rsrc_mgr.o bulkmem.o cs.o
pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
......
/*
* Generic PCI pccard driver interface.
*
* (C) Copyright 1999 Linus Torvalds
*
* This implements the common parts of PCI pccard drivers,
* notably detection and infrastructure conversion (ie change
* from socket index to "struct pci_dev" etc)
*
* This does NOT implement the actual low-level driver details,
* and this has on purpose been left generic enough that it can
* be used to set up a PCI PCMCIA controller (ie non-cardbus),
* or to set up a controller.
*
* See for example the "yenta" driver for PCI cardbus controllers
* conforming to the yenta cardbus specifications.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <pcmcia/ss.h>
#include <asm/io.h>
#include "pci_socket.h"
/*
* Arbitrary define. This is the array of active cardbus
* entries.
*/
#define MAX_SOCKETS (8)
static pci_socket_t pci_socket_array[MAX_SOCKETS];
static int pci_init_socket(struct pcmcia_socket *sock)
{
pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
if (socket->op && socket->op->init)
return socket->op->init(socket);
return -EINVAL;
}
static int pci_suspend_socket(struct pcmcia_socket *sock)
{
pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
if (socket->op && socket->op->suspend)
return socket->op->suspend(socket);
return -EINVAL;
}
static int pci_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
{
pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
socket->handler = handler;
socket->info = info;
return 0;
}
static int pci_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap)
{
pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
*cap = socket->cap;
return 0;
}
static int pci_get_status(struct pcmcia_socket *sock, unsigned int *value)
{
pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
if (socket->op && socket->op->get_status)
return socket->op->get_status(socket, value);
*value = 0;
return -EINVAL;
}
static int pci_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
if (socket->op && socket->op->get_socket)
return socket->op->get_socket(socket, state);
return -EINVAL;
}
static int pci_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
if (socket->op && socket->op->set_socket)
return socket->op->set_socket(socket, state);
return -EINVAL;
}
static int pci_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
{
pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
if (socket->op && socket->op->set_io_map)
return socket->op->set_io_map(socket, io);
return -EINVAL;
}
static int pci_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
{
pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
if (socket->op && socket->op->set_mem_map)
return socket->op->set_mem_map(socket, mem);
return -EINVAL;
}
static void pci_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
{
pci_socket_t *socket = container_of(sock, struct pci_socket, socket);
if (socket->op && socket->op->proc_setup)
socket->op->proc_setup(socket, base);
}
static struct pccard_operations pci_socket_operations = {
.owner = THIS_MODULE,
.init = pci_init_socket,
.suspend = pci_suspend_socket,
.register_callback = pci_register_callback,
.inquire_socket = pci_inquire_socket,
.get_status = pci_get_status,
.get_socket = pci_get_socket,
.set_socket = pci_set_socket,
.set_io_map = pci_set_io_map,
.set_mem_map = pci_set_mem_map,
.proc_setup = pci_proc_setup,
};
static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_ops *ops)
{
pci_socket_t *socket = nr + pci_socket_array;
int err;
memset(socket, 0, sizeof(*socket));
/* prepare pcmcia_socket */
socket->socket.ss_entry = &pci_socket_operations;
socket->socket.dev.dev = &dev->dev;
socket->socket.driver_data = socket;
/* prepare pci_socket_t */
socket->dev = dev;
socket->op = ops;
pci_set_drvdata(dev, socket);
spin_lock_init(&socket->event_lock);
err = socket->op->open(socket);
if (err) {
socket->dev = NULL;
pci_set_drvdata(dev, NULL);
} else {
pcmcia_register_socket(&socket->socket);
}
return err;
}
int cardbus_register(struct pci_dev *p_dev)
{
return 0;
}
static int __devinit
cardbus_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
int s;
for (s = 0; s < MAX_SOCKETS; s++) {
if (pci_socket_array [s].dev == 0) {
return add_pci_socket (s, dev, &yenta_operations);
}
}
return -ENODEV;
}
static void __devexit cardbus_remove (struct pci_dev *dev)
{
pci_socket_t *socket = pci_get_drvdata(dev);
/* note: we are already unregistered from the cs core */
pcmcia_unregister_socket(&socket->socket);
if (socket->op && socket->op->close)
socket->op->close(socket);
pci_set_drvdata(dev, NULL);
}
static int cardbus_suspend (struct pci_dev *dev, u32 state)
{
return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
}
static int cardbus_resume (struct pci_dev *dev)
{
return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
}
static struct pci_device_id cardbus_table [] __devinitdata = { {
.class = PCI_CLASS_BRIDGE_CARDBUS << 8,
.class_mask = ~0,
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
}, { /* all zeroes */ }
};
MODULE_DEVICE_TABLE(pci, cardbus_table);
static struct pci_driver pci_cardbus_driver = {
.name = "cardbus",
.id_table = cardbus_table,
.probe = cardbus_probe,
.remove = __devexit_p(cardbus_remove),
.suspend = cardbus_suspend,
.resume = cardbus_resume,
};
static int __init pci_socket_init(void)
{
return pci_register_driver (&pci_cardbus_driver);
}
static void __exit pci_socket_exit (void)
{
pci_unregister_driver (&pci_cardbus_driver);
}
module_init(pci_socket_init);
module_exit(pci_socket_exit);
/*
* drivers/pcmcia/pci_socket.h
*
* (C) Copyright 1999 Linus Torvalds
*/
#ifndef __PCI_SOCKET_H
#define __PCI_SOCKET_H
struct pci_socket_ops;
struct socket_info_t;
typedef struct pci_socket {
struct pci_dev *dev;
int cb_irq, io_irq;
void *base;
void (*handler)(void *, unsigned int);
void *info;
struct pci_socket_ops *op;
socket_cap_t cap;
spinlock_t event_lock;
unsigned int events;
struct work_struct tq_task;
struct timer_list poll_timer;
struct pcmcia_socket socket;
/* A few words of private data for the low-level driver.. */
unsigned int private[8];
} pci_socket_t;
struct pci_socket_ops {
int (*open)(struct pci_socket *);
void (*close)(struct pci_socket *);
int (*init)(struct pci_socket *);
int (*suspend)(struct pci_socket *);
int (*get_status)(struct pci_socket *, unsigned int *);
int (*get_socket)(struct pci_socket *, socket_state_t *);
int (*set_socket)(struct pci_socket *, socket_state_t *);
int (*set_io_map)(struct pci_socket *, struct pccard_io_map *);
int (*set_mem_map)(struct pci_socket *, struct pccard_mem_map *);
void (*proc_setup)(struct pci_socket *, struct proc_dir_entry *base);
};
extern struct pci_socket_ops yenta_operations;
extern struct pci_socket_ops ricoh_operations;
#endif
......@@ -125,11 +125,26 @@
#define rl_mem(socket) ((socket)->private[3])
#define rl_config(socket) ((socket)->private[4])
static int ricoh_init(struct pcmcia_socket *sock)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
yenta_init(sock);
config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket));
config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket));
config_writew(socket, RL5C4XX_CONFIG, rl_config(socket));
return 0;
}
/*
* Magic Ricoh initialization code.. Save state at
* beginning, re-initialize it after suspend.
*/
static int ricoh_open(pci_socket_t *socket)
static int ricoh_override(struct yenta_socket *socket)
{
rl_misc(socket) = config_readw(socket, RL5C4XX_MISC);
rl_ctl(socket) = config_readw(socket, RL5C4XX_16BIT_CTL);
......@@ -146,35 +161,11 @@ static int ricoh_open(pci_socket_t *socket)
rl_config(socket) |= RL5C4XX_CONFIG_PREFETCH;
}
return 0;
}
static int ricoh_init(pci_socket_t *socket)
{
yenta_init(socket);
socket->socket.ss_entry->init = ricoh_init;
config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket));
config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket));
config_writew(socket, RL5C4XX_CONFIG, rl_config(socket));
return 0;
}
static struct pci_socket_ops ricoh_ops = {
ricoh_open,
yenta_close,
ricoh_init,
yenta_suspend,
yenta_get_status,
yenta_get_socket,
yenta_set_socket,
yenta_set_io_map,
yenta_set_mem_map,
yenta_proc_setup
};
#endif /* CONFIG_CARDBUS */
#endif /* _LINUX_RICOH_H */
......@@ -136,6 +136,26 @@
#ifdef CONFIG_CARDBUS
static int ti_intctl(struct yenta_socket *socket)
{
u8 new, reg = exca_readb(socket, I365_INTCTL);
new = reg & ~I365_INTR_ENA;
if (socket->cb_irq)
new |= I365_INTR_ENA;
if (new != reg)
exca_writeb(socket, I365_INTCTL, new);
return 0;
}
static int ti_init(struct pcmcia_socket *sock)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
yenta_init(sock);
ti_intctl(socket);
return 0;
}
/*
* Generic TI init - TI has an extension for the
* INTCTL register that sets the PCI CSC interrupt.
......@@ -148,70 +168,28 @@
* This makes us correctly get PCI CSC interrupt
* events.
*/
static int ti_open(pci_socket_t *socket)
static int ti_override(struct yenta_socket *socket)
{
u8 new, reg = exca_readb(socket, I365_INTCTL);
new = reg & ~I365_INTR_ENA;
if (new != reg)
exca_writeb(socket, I365_INTCTL, new);
socket->socket.ss_entry->init = ti_init;
return 0;
}
static int ti_intctl(pci_socket_t *socket)
{
u8 new, reg = exca_readb(socket, I365_INTCTL);
new = reg & ~I365_INTR_ENA;
if (socket->cb_irq)
new |= I365_INTR_ENA;
if (new != reg)
exca_writeb(socket, I365_INTCTL, new);
return 0;
}
static int ti_init(pci_socket_t *socket)
{
yenta_init(socket);
ti_intctl(socket);
return 0;
}
static struct pci_socket_ops ti_ops = {
ti_open,
yenta_close,
ti_init,
yenta_suspend,
yenta_get_status,
yenta_get_socket,
yenta_set_socket,
yenta_set_io_map,
yenta_set_mem_map,
yenta_proc_setup
};
#define ti_sysctl(socket) ((socket)->private[0])
#define ti_cardctl(socket) ((socket)->private[1])
#define ti_devctl(socket) ((socket)->private[2])
#define ti_diag(socket) ((socket)->private[3])
#define ti_irqmux(socket) ((socket)->private[4])
static int ti113x_open(pci_socket_t *socket)
{
ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL);
ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL);
ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL);
ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
if (socket->cb_irq)
ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
ti_open(socket);
return 0;
}
static int ti113x_init(pci_socket_t *socket)
static int ti113x_init(struct pcmcia_socket *sock)
{
yenta_init(socket);
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
yenta_init(sock);
config_writel(socket, TI113X_SYSTEM_CONTROL, ti_sysctl(socket));
config_writeb(socket, TI113X_CARD_CONTROL, ti_cardctl(socket));
......@@ -220,35 +198,26 @@ static int ti113x_init(pci_socket_t *socket)
return 0;
}
static struct pci_socket_ops ti113x_ops = {
ti113x_open,
yenta_close,
ti113x_init,
yenta_suspend,
yenta_get_status,
yenta_get_socket,
yenta_set_socket,
yenta_set_io_map,
yenta_set_mem_map,
yenta_proc_setup
};
static int ti1250_open(pci_socket_t *socket)
static int ti113x_override(struct yenta_socket *socket)
{
ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC);
ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL);
ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL);
ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL);
ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ);
ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
if (socket->cb_irq)
ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
ti113x_open(socket);
ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
ti_override(socket);
socket->socket.ss_entry->init = ti113x_init;
return 0;
}
static int ti1250_init(pci_socket_t *socket)
static int ti1250_init(struct pcmcia_socket *sock)
{
yenta_init(socket);
ti113x_init(socket);
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
yenta_init(sock);
ti113x_init(sock);
ti_irqmux(socket) = config_readl(socket, TI122X_IRQMUX);
ti_irqmux(socket) = (ti_irqmux(socket) & ~0x0f) | 0x02; /* route INTA */
if (!(ti_sysctl(socket) & TI122X_SCR_INTRTIE))
......@@ -260,18 +229,17 @@ static int ti1250_init(pci_socket_t *socket)
return 0;
}
static struct pci_socket_ops ti1250_ops = {
ti1250_open,
yenta_close,
ti1250_init,
yenta_suspend,
yenta_get_status,
yenta_get_socket,
yenta_set_socket,
yenta_set_io_map,
yenta_set_mem_map,
yenta_proc_setup
};
static int ti1250_override(struct yenta_socket *socket)
{
ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC);
ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ);
if (socket->cb_irq)
ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
ti113x_override(socket);
socket->socket.ss_entry->init = ti1250_init;
return 0;
}
#endif /* CONFIG_CARDBUS */
......
This diff is collapsed.
......@@ -2,7 +2,6 @@
#define __YENTA_H
#include <asm/io.h>
#include "pci_socket.h"
#define CB_SOCKET_EVENT 0x00
#define CB_CSTSEVENT 0x00000001 /* Card status event */
......@@ -96,4 +95,23 @@
*/
#define CB_MEM_PAGE(map) (0x40 + (map))
struct yenta_socket {
struct pci_dev *dev;
int cb_irq, io_irq;
void *base;
void (*handler)(void *, unsigned int);
void *info;
socket_cap_t cap;
spinlock_t event_lock;
unsigned int events;
struct work_struct tq_task;
struct timer_list poll_timer;
struct pcmcia_socket socket;
/* A few words of private data for special stuff of overrides... */
unsigned int private[8];
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment