#include <linux/tifm.h>
#include <linux/dma-mapping.h>
-#include <linux/freezer.h>
#define DRIVER_NAME "tifm_7xx1"
#define DRIVER_VERSION "0.8"
{
struct tifm_adapter *fm = dev_id;
struct tifm_dev *sock;
- unsigned int irq_status;
- unsigned int cnt;
+ unsigned int irq_status, cnt;
spin_lock(&fm->lock);
irq_status = readl(fm->addr + FM_INTERRUPT_STATUS);
== TIFM_TYPE_XD)
msleep(40);
- writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL);
+ writel((s_state & TIFM_CTRL_POWER_MASK) | 0x0c00,
+ sock_addr + SOCK_CONTROL);
/* wait for power to stabilize */
msleep(20);
for (cnt = 16; cnt <= 256; cnt <<= 1) {
return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7;
}
+inline static void tifm_7xx1_sock_power_off(char __iomem *sock_addr)
+{
+ writel((~TIFM_CTRL_POWER_MASK) & readl(sock_addr + SOCK_CONTROL),
+ sock_addr + SOCK_CONTROL);
+}
+
inline static char __iomem *
tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num)
{
{
struct tifm_adapter *fm = container_of(work, struct tifm_adapter,
media_switcher);
+ struct tifm_dev *sock;
+ char __iomem *sock_addr;
unsigned long flags;
unsigned char media_id;
- int cnt;
- struct tifm_dev *sock;
- unsigned int socket_change_set;
+ unsigned int socket_change_set, cnt;
spin_lock_irqsave(&fm->lock, flags);
socket_change_set = fm->socket_change_set;
fm->socket_change_set = 0;
- dev_dbg(fm->cdev.dev, "checking media set %x\n",
+ dev_dbg(fm->dev.parent, "checking media set %x\n",
socket_change_set);
if (!socket_change_set) {
if (sock) {
printk(KERN_INFO
"%s : demand removing card from socket %u:%u\n",
- fm->cdev.class_id, fm->id, cnt);
+ dev_name(&fm->dev), fm->id, cnt);
fm->sockets[cnt] = NULL;
+ sock_addr = sock->addr;
spin_unlock_irqrestore(&fm->lock, flags);
device_unregister(&sock->dev);
spin_lock_irqsave(&fm->lock, flags);
- writel(0x0e00, tifm_7xx1_sock_addr(fm->addr, cnt)
- + SOCK_CONTROL);
+ tifm_7xx1_sock_power_off(sock_addr);
+ writel(0x0e00, sock_addr + SOCK_CONTROL);
}
spin_unlock_irqrestore(&fm->lock, flags);
static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state)
{
+ struct tifm_adapter *fm = pci_get_drvdata(dev);
+ int cnt;
+
dev_dbg(&dev->dev, "suspending host\n");
+ for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+ if (fm->sockets[cnt])
+ tifm_7xx1_sock_power_off(fm->sockets[cnt]->addr);
+ }
+
pci_save_state(dev);
pci_enable_wake(dev, pci_choose_state(dev, state), 0);
pci_disable_device(dev);
#endif /* CONFIG_PM */
+static int tifm_7xx1_dummy_has_ms_pif(struct tifm_adapter *fm,
+ struct tifm_dev *sock)
+{
+ return 0;
+}
+
+static int tifm_7xx1_has_ms_pif(struct tifm_adapter *fm, struct tifm_dev *sock)
+{
+ if (((fm->num_sockets == 4) && (sock->socket_id == 2))
+ || ((fm->num_sockets == 2) && (sock->socket_id == 0)))
+ return 1;
+
+ return 0;
+}
+
static int tifm_7xx1_probe(struct pci_dev *dev,
const struct pci_device_id *dev_id)
{
int pci_dev_busy = 0;
int rc;
- rc = pci_set_dma_mask(dev, DMA_32BIT_MASK);
+ rc = pci_set_dma_mask(dev, DMA_BIT_MASK(32));
if (rc)
return rc;
INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media);
fm->eject = tifm_7xx1_eject;
+ fm->has_ms_pif = tifm_7xx1_has_ms_pif;
pci_set_drvdata(dev, fm);
- fm->addr = ioremap(pci_resource_start(dev, 0),
- pci_resource_len(dev, 0));
+ fm->addr = pci_ioremap_bar(dev, 0);
if (!fm->addr)
goto err_out_free;
- rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm);
+ rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
if (rc)
goto err_out_unmap;
goto err_out_irq;
writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
+ fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+ writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
fm->addr + FM_SET_INTERRUPT_ENABLE);
return 0;
static void tifm_7xx1_remove(struct pci_dev *dev)
{
struct tifm_adapter *fm = pci_get_drvdata(dev);
+ int cnt;
fm->eject = tifm_7xx1_dummy_eject;
+ fm->has_ms_pif = tifm_7xx1_dummy_has_ms_pif;
writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
mmiowb();
free_irq(dev->irq, fm);
tifm_remove_adapter(fm);
+ for (cnt = 0; cnt < fm->num_sockets; cnt++)
+ tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt));
+
pci_set_drvdata(dev, NULL);
iounmap(fm->addr);