Blame view

drivers/mfd/lpc_sch.c 4.93 KB
e82c60ae7   Denis Turischev   mfd: Introduce lp...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  /*
   *  lpc_sch.c - LPC interface for Intel Poulsbo SCH
   *
   *  LPC bridge function of the Intel SCH contains many other
   *  functional units, such as Interrupt controllers, Timers,
   *  Power Management, System Management, GPIO, RTC, and LPC
   *  Configuration Registers.
   *
   *  Copyright (c) 2010 CompuLab Ltd
   *  Author: Denis Turischev <denis@compulab.co.il>
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License 2 as published
   *  by the Free Software Foundation.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program; see the file COPYING.  If not, write to
   *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
   */
  
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/errno.h>
  #include <linux/acpi.h>
  #include <linux/pci.h>
  #include <linux/mfd/core.h>
  
  #define SMBASE		0x40
  #define SMBUS_IO_SIZE	64
  
  #define GPIOBASE	0x44
  #define GPIO_IO_SIZE	64
8ee3c2a79   Seth Heasley   lpc_sch: Add Inte...
39
  #define GPIO_IO_SIZE_CENTERTON	128
e82c60ae7   Denis Turischev   mfd: Introduce lp...
40

19921ef61   Alexander Stein   mfd: Add tunnelcr...
41
42
  #define WDTBASE		0x84
  #define WDT_IO_SIZE	64
e82c60ae7   Denis Turischev   mfd: Introduce lp...
43
44
45
  static struct resource smbus_sch_resource = {
  		.flags = IORESOURCE_IO,
  };
e82c60ae7   Denis Turischev   mfd: Introduce lp...
46
47
48
  static struct resource gpio_sch_resource = {
  		.flags = IORESOURCE_IO,
  };
19921ef61   Alexander Stein   mfd: Add tunnelcr...
49
50
51
  static struct resource wdt_sch_resource = {
  		.flags = IORESOURCE_IO,
  };
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
52
53
54
55
56
57
  static struct mfd_cell lpc_sch_cells[3];
  
  static struct mfd_cell isch_smbus_cell = {
  	.name = "isch_smbus",
  	.num_resources = 1,
  	.resources = &smbus_sch_resource,
6bfd1e63d   Johannes Thumshirn   mfd: lpc_sch: Ign...
58
  	.ignore_resource_conflicts = true,
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
59
60
61
62
63
64
  };
  
  static struct mfd_cell sch_gpio_cell = {
  	.name = "sch_gpio",
  	.num_resources = 1,
  	.resources = &gpio_sch_resource,
6bfd1e63d   Johannes Thumshirn   mfd: lpc_sch: Ign...
65
  	.ignore_resource_conflicts = true,
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
66
67
68
69
70
71
  };
  
  static struct mfd_cell wdt_sch_cell = {
  	.name = "ie6xx_wdt",
  	.num_resources = 1,
  	.resources = &wdt_sch_resource,
6bfd1e63d   Johannes Thumshirn   mfd: lpc_sch: Ign...
72
  	.ignore_resource_conflicts = true,
19921ef61   Alexander Stein   mfd: Add tunnelcr...
73
  };
36fcd06c4   Jingoo Han   mfd: Remove DEFIN...
74
  static const struct pci_device_id lpc_sch_ids[] = {
e82c60ae7   Denis Turischev   mfd: Introduce lp...
75
  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
e967f77d9   Denis Turischev   mfd: Add Tunnel C...
76
  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) },
8ee3c2a79   Seth Heasley   lpc_sch: Add Inte...
77
  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB) },
e82c60ae7   Denis Turischev   mfd: Introduce lp...
78
79
80
  	{ 0, }
  };
  MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
f791be492   Bill Pemberton   mfd: remove use o...
81
  static int lpc_sch_probe(struct pci_dev *dev,
e82c60ae7   Denis Turischev   mfd: Introduce lp...
82
83
84
85
  				const struct pci_device_id *id)
  {
  	unsigned int base_addr_cfg;
  	unsigned short base_addr;
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
86
  	int i, cells = 0;
19921ef61   Alexander Stein   mfd: Add tunnelcr...
87
  	int ret;
e82c60ae7   Denis Turischev   mfd: Introduce lp...
88
89
  
  	pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
90
91
92
93
94
95
  	base_addr = 0;
  	if (!(base_addr_cfg & (1 << 31)))
  		dev_warn(&dev->dev, "Decode of the SMBus I/O range disabled
  ");
  	else
  		base_addr = (unsigned short)base_addr_cfg;
e82c60ae7   Denis Turischev   mfd: Introduce lp...
96

e82c60ae7   Denis Turischev   mfd: Introduce lp...
97
  	if (base_addr == 0) {
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
98
99
100
101
102
103
  		dev_warn(&dev->dev, "I/O space for SMBus uninitialized
  ");
  	} else {
  		lpc_sch_cells[cells++] = isch_smbus_cell;
  		smbus_sch_resource.start = base_addr;
  		smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1;
e82c60ae7   Denis Turischev   mfd: Introduce lp...
104
  	}
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
105
106
107
108
109
  	pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg);
  	base_addr = 0;
  	if (!(base_addr_cfg & (1 << 31)))
  		dev_warn(&dev->dev, "Decode of the GPIO I/O range disabled
  ");
8ee3c2a79   Seth Heasley   lpc_sch: Add Inte...
110
  	else
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
111
  		base_addr = (unsigned short)base_addr_cfg;
e967f77d9   Denis Turischev   mfd: Add Tunnel C...
112

5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
113
114
115
116
117
118
119
120
121
122
123
  	if (base_addr == 0) {
  		dev_warn(&dev->dev, "I/O space for GPIO uninitialized
  ");
  	} else {
  		lpc_sch_cells[cells++] = sch_gpio_cell;
  		gpio_sch_resource.start = base_addr;
  		if (id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB)
  			gpio_sch_resource.end = base_addr + GPIO_IO_SIZE_CENTERTON - 1;
  		else
  			gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1;
  	}
19921ef61   Alexander Stein   mfd: Add tunnelcr...
124

8ee3c2a79   Seth Heasley   lpc_sch: Add Inte...
125
  	if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
126
  	    || id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) {
19921ef61   Alexander Stein   mfd: Add tunnelcr...
127
  		pci_read_config_dword(dev, WDTBASE, &base_addr_cfg);
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
128
129
130
131
132
133
134
135
136
137
138
139
140
  		base_addr = 0;
  		if (!(base_addr_cfg & (1 << 31)))
  			dev_warn(&dev->dev, "Decode of the WDT I/O range disabled
  ");
  		else
  			base_addr = (unsigned short)base_addr_cfg;
  		if (base_addr == 0)
  			dev_warn(&dev->dev, "I/O space for WDT uninitialized
  ");
  		else {
  			lpc_sch_cells[cells++] = wdt_sch_cell;
  			wdt_sch_resource.start = base_addr;
  			wdt_sch_resource.end = base_addr + WDT_IO_SIZE - 1;
19921ef61   Alexander Stein   mfd: Add tunnelcr...
141
  		}
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
142
  	}
19921ef61   Alexander Stein   mfd: Add tunnelcr...
143

5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
144
145
146
147
  	if (WARN_ON(cells > ARRAY_SIZE(lpc_sch_cells))) {
  		dev_err(&dev->dev, "Cell count exceeds array size");
  		return -ENODEV;
  	}
19921ef61   Alexander Stein   mfd: Add tunnelcr...
148

5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
149
150
151
152
  	if (cells == 0) {
  		dev_err(&dev->dev, "All decode registers disabled.
  ");
  		return -ENODEV;
19921ef61   Alexander Stein   mfd: Add tunnelcr...
153
  	}
5829e9b64   Darren Hart   mfd: lpc_sch: Acc...
154
155
156
157
158
159
  	for (i = 0; i < cells; i++)
  		lpc_sch_cells[i].id = id->device;
  
  	ret = mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL);
  	if (ret)
  		mfd_remove_devices(&dev->dev);
19921ef61   Alexander Stein   mfd: Add tunnelcr...
160
  	return ret;
e82c60ae7   Denis Turischev   mfd: Introduce lp...
161
  }
4740f73fe   Bill Pemberton   mfd: remove use o...
162
  static void lpc_sch_remove(struct pci_dev *dev)
e82c60ae7   Denis Turischev   mfd: Introduce lp...
163
164
165
166
167
168
169
170
  {
  	mfd_remove_devices(&dev->dev);
  }
  
  static struct pci_driver lpc_sch_driver = {
  	.name		= "lpc_sch",
  	.id_table	= lpc_sch_ids,
  	.probe		= lpc_sch_probe,
84449216b   Bill Pemberton   mfd: remove use o...
171
  	.remove		= lpc_sch_remove,
e82c60ae7   Denis Turischev   mfd: Introduce lp...
172
  };
38a36f5a6   Axel Lin   mfd: Use module_p...
173
  module_pci_driver(lpc_sch_driver);
e82c60ae7   Denis Turischev   mfd: Introduce lp...
174
175
176
177
  
  MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
  MODULE_DESCRIPTION("LPC interface for Intel Poulsbo SCH");
  MODULE_LICENSE("GPL");