aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/lpc_sch.c147
1 files changed, 71 insertions, 76 deletions
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
index 5624fcbba69b..8cc6aac27cb2 100644
--- a/drivers/mfd/lpc_sch.c
+++ b/drivers/mfd/lpc_sch.c
@@ -45,34 +45,32 @@ static struct resource smbus_sch_resource = {
45 .flags = IORESOURCE_IO, 45 .flags = IORESOURCE_IO,
46}; 46};
47 47
48
49static struct resource gpio_sch_resource = { 48static struct resource gpio_sch_resource = {
50 .flags = IORESOURCE_IO, 49 .flags = IORESOURCE_IO,
51}; 50};
52 51
53static struct mfd_cell lpc_sch_cells[] = {
54 {
55 .name = "isch_smbus",
56 .num_resources = 1,
57 .resources = &smbus_sch_resource,
58 },
59 {
60 .name = "sch_gpio",
61 .num_resources = 1,
62 .resources = &gpio_sch_resource,
63 },
64};
65
66static struct resource wdt_sch_resource = { 52static struct resource wdt_sch_resource = {
67 .flags = IORESOURCE_IO, 53 .flags = IORESOURCE_IO,
68}; 54};
69 55
70static struct mfd_cell tunnelcreek_cells[] = { 56static struct mfd_cell lpc_sch_cells[3];
71 { 57
72 .name = "ie6xx_wdt", 58static struct mfd_cell isch_smbus_cell = {
73 .num_resources = 1, 59 .name = "isch_smbus",
74 .resources = &wdt_sch_resource, 60 .num_resources = 1,
75 }, 61 .resources = &smbus_sch_resource,
62};
63
64static struct mfd_cell sch_gpio_cell = {
65 .name = "sch_gpio",
66 .num_resources = 1,
67 .resources = &gpio_sch_resource,
68};
69
70static struct mfd_cell wdt_sch_cell = {
71 .name = "ie6xx_wdt",
72 .num_resources = 1,
73 .resources = &wdt_sch_resource,
76}; 74};
77 75
78static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = { 76static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = {
@@ -88,79 +86,76 @@ static int lpc_sch_probe(struct pci_dev *dev,
88{ 86{
89 unsigned int base_addr_cfg; 87 unsigned int base_addr_cfg;
90 unsigned short base_addr; 88 unsigned short base_addr;
91 int i; 89 int i, cells = 0;
92 int ret; 90 int ret;
93 91
94 pci_read_config_dword(dev, SMBASE, &base_addr_cfg); 92 pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
95 if (!(base_addr_cfg & (1 << 31))) { 93 base_addr = 0;
96 dev_err(&dev->dev, "Decode of the SMBus I/O range disabled\n"); 94 if (!(base_addr_cfg & (1 << 31)))
97 return -ENODEV; 95 dev_warn(&dev->dev, "Decode of the SMBus I/O range disabled\n");
98 } 96 else
99 base_addr = (unsigned short)base_addr_cfg; 97 base_addr = (unsigned short)base_addr_cfg;
100 if (base_addr == 0) {
101 dev_err(&dev->dev, "I/O space for SMBus uninitialized\n");
102 return -ENODEV;
103 }
104
105 smbus_sch_resource.start = base_addr;
106 smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1;
107 98
108 pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg);
109 if (!(base_addr_cfg & (1 << 31))) {
110 dev_err(&dev->dev, "Decode of the GPIO I/O range disabled\n");
111 return -ENODEV;
112 }
113 base_addr = (unsigned short)base_addr_cfg;
114 if (base_addr == 0) { 99 if (base_addr == 0) {
115 dev_err(&dev->dev, "I/O space for GPIO uninitialized\n"); 100 dev_warn(&dev->dev, "I/O space for SMBus uninitialized\n");
116 return -ENODEV; 101 } else {
102 lpc_sch_cells[cells++] = isch_smbus_cell;
103 smbus_sch_resource.start = base_addr;
104 smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1;
117 } 105 }
118 106
119 gpio_sch_resource.start = base_addr; 107 pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg);
120 108 base_addr = 0;
121 if (id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) 109 if (!(base_addr_cfg & (1 << 31)))
122 gpio_sch_resource.end = base_addr + GPIO_IO_SIZE_CENTERTON - 1; 110 dev_warn(&dev->dev, "Decode of the GPIO I/O range disabled\n");
123 else 111 else
124 gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1; 112 base_addr = (unsigned short)base_addr_cfg;
125
126 for (i=0; i < ARRAY_SIZE(lpc_sch_cells); i++)
127 lpc_sch_cells[i].id = id->device;
128 113
129 ret = mfd_add_devices(&dev->dev, 0, 114 if (base_addr == 0) {
130 lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 115 dev_warn(&dev->dev, "I/O space for GPIO uninitialized\n");
131 0, NULL); 116 } else {
132 if (ret) 117 lpc_sch_cells[cells++] = sch_gpio_cell;
133 goto out_dev; 118 gpio_sch_resource.start = base_addr;
119 if (id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB)
120 gpio_sch_resource.end = base_addr + GPIO_IO_SIZE_CENTERTON - 1;
121 else
122 gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1;
123 }
134 124
135 if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC 125 if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC
136 || id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) { 126 || id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) {
137 pci_read_config_dword(dev, WDTBASE, &base_addr_cfg); 127 pci_read_config_dword(dev, WDTBASE, &base_addr_cfg);
138 if (!(base_addr_cfg & (1 << 31))) { 128 base_addr = 0;
139 dev_err(&dev->dev, "Decode of the WDT I/O range disabled\n"); 129 if (!(base_addr_cfg & (1 << 31)))
140 ret = -ENODEV; 130 dev_warn(&dev->dev, "Decode of the WDT I/O range disabled\n");
141 goto out_dev; 131 else
132 base_addr = (unsigned short)base_addr_cfg;
133 if (base_addr == 0)
134 dev_warn(&dev->dev, "I/O space for WDT uninitialized\n");
135 else {
136 lpc_sch_cells[cells++] = wdt_sch_cell;
137 wdt_sch_resource.start = base_addr;
138 wdt_sch_resource.end = base_addr + WDT_IO_SIZE - 1;
142 } 139 }
143 base_addr = (unsigned short)base_addr_cfg; 140 }
144 if (base_addr == 0) {
145 dev_err(&dev->dev, "I/O space for WDT uninitialized\n");
146 ret = -ENODEV;
147 goto out_dev;
148 }
149
150 wdt_sch_resource.start = base_addr;
151 wdt_sch_resource.end = base_addr + WDT_IO_SIZE - 1;
152 141
153 for (i = 0; i < ARRAY_SIZE(tunnelcreek_cells); i++) 142 if (WARN_ON(cells > ARRAY_SIZE(lpc_sch_cells))) {
154 tunnelcreek_cells[i].id = id->device; 143 dev_err(&dev->dev, "Cell count exceeds array size");
144 return -ENODEV;
145 }
155 146
156 ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells, 147 if (cells == 0) {
157 ARRAY_SIZE(tunnelcreek_cells), NULL, 148 dev_err(&dev->dev, "All decode registers disabled.\n");
158 0, NULL); 149 return -ENODEV;
159 } 150 }
160 151
161 return ret; 152 for (i = 0; i < cells; i++)
162out_dev: 153 lpc_sch_cells[i].id = id->device;
163 mfd_remove_devices(&dev->dev); 154
155 ret = mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL);
156 if (ret)
157 mfd_remove_devices(&dev->dev);
158
164 return ret; 159 return ret;
165} 160}
166 161