OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [mmc/] [host/] [ricoh_mmc.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  ricoh_mmc.c - Dummy driver to disable the Rioch MMC controller.
3
 *
4
 *  Copyright (C) 2007 Philip Langdale, All Rights Reserved.
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or (at
9
 * your option) any later version.
10
 */
11
 
12
/*
13
 * This is a conceptually ridiculous driver, but it is required by the way
14
 * the Ricoh multi-function R5C832 works. This chip implements firewire
15
 * and four different memory card controllers. Two of those controllers are
16
 * an SDHCI controller and a proprietary MMC controller. The linux SDHCI
17
 * driver supports MMC cards but the chip detects MMC cards in hardware
18
 * and directs them to the MMC controller - so the SDHCI driver never sees
19
 * them. To get around this, we must disable the useless MMC controller.
20
 * At that point, the SDHCI controller will start seeing them. As a bonus,
21
 * a detection event occurs immediately, even if the MMC card is already
22
 * in the reader.
23
 *
24
 * The relevant registers live on the firewire function, so this is unavoidably
25
 * ugly. Such is life.
26
 */
27
 
28
#include <linux/pci.h>
29
 
30
#define DRIVER_NAME "ricoh-mmc"
31
 
32
static const struct pci_device_id pci_ids[] __devinitdata = {
33
        {
34
                .vendor         = PCI_VENDOR_ID_RICOH,
35
                .device         = PCI_DEVICE_ID_RICOH_R5C843,
36
                .subvendor      = PCI_ANY_ID,
37
                .subdevice      = PCI_ANY_ID,
38
        },
39
        { /* end: all zeroes */ },
40
};
41
 
42
MODULE_DEVICE_TABLE(pci, pci_ids);
43
 
44
static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
45
                                     const struct pci_device_id *ent)
46
{
47
        u8 rev;
48
 
49
        struct pci_dev *fw_dev = NULL;
50
 
51
        BUG_ON(pdev == NULL);
52
        BUG_ON(ent == NULL);
53
 
54
        pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
55
 
56
        printk(KERN_INFO DRIVER_NAME
57
                ": Ricoh MMC controller found at %s [%04x:%04x] (rev %x)\n",
58
                pci_name(pdev), (int)pdev->vendor, (int)pdev->device,
59
                (int)rev);
60
 
61
        while ((fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) {
62
                if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
63
                    pdev->bus == fw_dev->bus) {
64
                        u8 write_enable;
65
                        u8 disable;
66
 
67
                        pci_read_config_byte(fw_dev, 0xCB, &disable);
68
                        if (disable & 0x02) {
69
                                printk(KERN_INFO DRIVER_NAME
70
                                       ": Controller already disabled. Nothing to do.\n");
71
                                return -ENODEV;
72
                        }
73
 
74
                        pci_read_config_byte(fw_dev, 0xCA, &write_enable);
75
                        pci_write_config_byte(fw_dev, 0xCA, 0x57);
76
                        pci_write_config_byte(fw_dev, 0xCB, disable | 0x02);
77
                        pci_write_config_byte(fw_dev, 0xCA, write_enable);
78
 
79
                        pci_set_drvdata(pdev, fw_dev);
80
 
81
                        printk(KERN_INFO DRIVER_NAME
82
                               ": Controller is now disabled.\n");
83
 
84
                        break;
85
                }
86
        }
87
 
88
        if (pci_get_drvdata(pdev) == NULL) {
89
                printk(KERN_WARNING DRIVER_NAME
90
                       ": Main firewire function not found. Cannot disable controller.\n");
91
                return -ENODEV;
92
        }
93
 
94
        return 0;
95
}
96
 
97
static void __devexit ricoh_mmc_remove(struct pci_dev *pdev)
98
{
99
        u8 write_enable;
100
        u8 disable;
101
        struct pci_dev *fw_dev = NULL;
102
 
103
        fw_dev = pci_get_drvdata(pdev);
104
        BUG_ON(fw_dev == NULL);
105
 
106
        pci_read_config_byte(fw_dev, 0xCA, &write_enable);
107
        pci_read_config_byte(fw_dev, 0xCB, &disable);
108
        pci_write_config_byte(fw_dev, 0xCA, 0x57);
109
        pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02);
110
        pci_write_config_byte(fw_dev, 0xCA, write_enable);
111
 
112
        printk(KERN_INFO DRIVER_NAME
113
               ": Controller is now re-enabled.\n");
114
 
115
        pci_set_drvdata(pdev, NULL);
116
}
117
 
118
static struct pci_driver ricoh_mmc_driver = {
119
        .name =         DRIVER_NAME,
120
        .id_table =     pci_ids,
121
        .probe =        ricoh_mmc_probe,
122
        .remove =       __devexit_p(ricoh_mmc_remove),
123
};
124
 
125
/*****************************************************************************\
126
 *                                                                           *
127
 * Driver init/exit                                                          *
128
 *                                                                           *
129
\*****************************************************************************/
130
 
131
static int __init ricoh_mmc_drv_init(void)
132
{
133
        printk(KERN_INFO DRIVER_NAME
134
                ": Ricoh MMC Controller disabling driver\n");
135
        printk(KERN_INFO DRIVER_NAME ": Copyright(c) Philip Langdale\n");
136
 
137
        return pci_register_driver(&ricoh_mmc_driver);
138
}
139
 
140
static void __exit ricoh_mmc_drv_exit(void)
141
{
142
        pci_unregister_driver(&ricoh_mmc_driver);
143
}
144
 
145
module_init(ricoh_mmc_drv_init);
146
module_exit(ricoh_mmc_drv_exit);
147
 
148
MODULE_AUTHOR("Philip Langdale <philipl@alumni.utexas.net>");
149
MODULE_DESCRIPTION("Ricoh MMC Controller disabling driver");
150
MODULE_LICENSE("GPL");
151
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.