0e95d08e880dbd39e6f48490313d917634c38dde
[coreboot.git] / src / southbridge / ti / pci7420 / pci7420_cardbus.c
1 /*
2  * (C) Copyright 2008-2009 coresystems GmbH
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
17  * MA 02110-1301 USA
18  */
19
20 #include <arch/io.h>
21 #include <device/device.h>
22 #include <device/pci.h>
23 #include <device/pci_ops.h>
24 #include <device/pci_ids.h>
25 #include <console/console.h>
26 #include <device/cardbus.h>
27 #include "pci7420.h"
28 #include "chip.h"
29
30 #ifdef ODD_IRQ_FIXUP
31 static int cardbus_count = 0;
32 #endif
33
34 static void pci7420_cardbus_init(device_t dev)
35 {
36         u8 reg8;
37         u16 reg16;
38         u32 reg32;
39
40         struct southbridge_ti_pci7420_config *config = dev->chip_info;
41         int smartcard_enabled = 0;
42
43         printk_debug("TI PCI7420/7620 init\n");
44
45         if (!config) {
46                 printk_debug("PCI7420: No configuration found.\n");
47         } else {
48                 smartcard_enabled = config->smartcard_enabled;
49         }
50
51         reg32 = pci_read_config32(dev, SYSCTL);
52         reg32 |= RIMUX;
53         pci_write_config32(dev, SYSCTL, reg32);
54
55         /* Enable SPKROUT */
56         reg8 = pci_read_config8(dev, CARDCTL);
57         reg8 |= SPKROUTEN;
58         pci_write_config8(dev, CARDCTL, reg8);
59
60         /* Power switch select and FM disable */
61         reg16 = pci_read_config16(dev, GENCTL);
62         reg16 |= P12V_SW_SEL; // 12V capable power switch
63         if (smartcard_enabled == 0)
64                 reg16 |= DISABLE_FM;
65         pci_write_config16(dev, GENCTL, reg16);
66
67         /* Multifunction routing status */
68         pci_write_config32(dev, MFUNC, 0x018a1b22);
69
70 #ifdef ODD_IRQ_FIXUP
71         /* This is a workaround for buggy kernels. This should
72          * probably be read from the device tree, but as long
73          * as only one mainboard is using this bridge it does
74          * not matter.
75          *
76          * Basically what we do here is assign INTA to the first
77          * cardbus controller, and INTB to the second one. We know
78          * there are only two of them.
79          */
80         pci_write_config8(dev, PCI_INTERRUPT_PIN, cardbus_count);
81         cardbus_count++;
82 #endif
83 }
84
85 void pci7420_cardbus_read_resources(device_t dev)
86 {
87         cardbus_read_resources(dev);
88 }
89
90 void pci7420_cardbus_set_resources(device_t dev)
91 {
92         printk_debug("%s In set resources \n",dev_path(dev));
93
94         pci_dev_set_resources(dev);
95
96         printk_debug("%s done set resources \n",dev_path(dev));
97 }
98
99 static struct device_operations ti_pci7420_ops = {
100         .read_resources   = pci7420_cardbus_read_resources,
101         .set_resources    = pci7420_cardbus_set_resources,
102         .enable_resources = cardbus_enable_resources,
103         .init             = pci7420_cardbus_init,
104         .scan_bus         = cardbus_scan_bridge,
105 };
106
107 static const struct pci_driver ti_pci7420_driver __pci_driver = {
108         .ops    = &ti_pci7420_ops,
109         .vendor = 0x104c,
110         .device = 0xac8e,
111 };
112
113 static const struct pci_driver ti_pci7620_driver __pci_driver = {
114         .ops    = &ti_pci7420_ops,
115         .vendor = 0x104c,
116         .device = 0xac8d,
117 };
118
119 static void ti_pci7420_enable_dev(device_t dev)
120 {
121         /* Nothing here yet */
122 }
123
124 struct chip_operations southbridge_ti_pci7420_ops = {
125         CHIP_NAME("Texas Instruments PCI7420/7620 Cardbus Controller")
126         .enable_dev    = ti_pci7420_enable_dev,
127 };