Blame view

drivers/mfd/cs5535-mfd.c 4.7 KB
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
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
  /*
   * cs5535-mfd.c - core MFD driver for CS5535/CS5536 southbridges
   *
   * The CS5535 and CS5536 has an ISA bridge on the PCI bus that is
   * used for accessing GPIOs, MFGPTs, ACPI, etc.  Each subdevice has
   * an IO range that's specified in a single BAR.  The BAR order is
   * hardcoded in the CS553x specifications.
   *
   * Copyright (c) 2010  Andres Salomon <dilinger@queued.net>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 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; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */
  
  #include <linux/kernel.h>
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
26
27
28
  #include <linux/mfd/core.h>
  #include <linux/module.h>
  #include <linux/pci.h>
fa1df6916   Andres Salomon   mfd: Add mfd_clon...
29
  #include <asm/olpc.h>
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
30
31
32
33
34
35
36
37
38
39
40
  
  #define DRV_NAME "cs5535-mfd"
  
  enum cs5535_mfd_bars {
  	SMB_BAR = 0,
  	GPIO_BAR = 1,
  	MFGPT_BAR = 2,
  	PMS_BAR = 4,
  	ACPI_BAR = 5,
  	NR_BARS,
  };
1310e6d63   Andres Salomon   mfd: Add sharing ...
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  static int cs5535_mfd_res_enable(struct platform_device *pdev)
  {
  	struct resource *res;
  
  	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
  	if (!res) {
  		dev_err(&pdev->dev, "can't fetch device resource info
  ");
  		return -EIO;
  	}
  
  	if (!request_region(res->start, resource_size(res), DRV_NAME)) {
  		dev_err(&pdev->dev, "can't request region
  ");
  		return -EIO;
  	}
  
  	return 0;
  }
  
  static int cs5535_mfd_res_disable(struct platform_device *pdev)
  {
  	struct resource *res;
  	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
  	if (!res) {
  		dev_err(&pdev->dev, "can't fetch device resource info
  ");
  		return -EIO;
  	}
  
  	release_region(res->start, resource_size(res));
  	return 0;
  }
a9e9ce4c4   Bill Pemberton   mfd: remove use o...
74
  static struct resource cs5535_mfd_resources[NR_BARS];
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
75

a9e9ce4c4   Bill Pemberton   mfd: remove use o...
76
  static struct mfd_cell cs5535_mfd_cells[] = {
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  	{
  		.id = SMB_BAR,
  		.name = "cs5535-smb",
  		.num_resources = 1,
  		.resources = &cs5535_mfd_resources[SMB_BAR],
  	},
  	{
  		.id = GPIO_BAR,
  		.name = "cs5535-gpio",
  		.num_resources = 1,
  		.resources = &cs5535_mfd_resources[GPIO_BAR],
  	},
  	{
  		.id = MFGPT_BAR,
  		.name = "cs5535-mfgpt",
  		.num_resources = 1,
  		.resources = &cs5535_mfd_resources[MFGPT_BAR],
  	},
  	{
  		.id = PMS_BAR,
  		.name = "cs5535-pms",
  		.num_resources = 1,
  		.resources = &cs5535_mfd_resources[PMS_BAR],
1310e6d63   Andres Salomon   mfd: Add sharing ...
100
101
102
  
  		.enable = cs5535_mfd_res_enable,
  		.disable = cs5535_mfd_res_disable,
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
103
104
105
106
107
108
  	},
  	{
  		.id = ACPI_BAR,
  		.name = "cs5535-acpi",
  		.num_resources = 1,
  		.resources = &cs5535_mfd_resources[ACPI_BAR],
1310e6d63   Andres Salomon   mfd: Add sharing ...
109
110
111
  
  		.enable = cs5535_mfd_res_enable,
  		.disable = cs5535_mfd_res_disable,
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
112
113
  	},
  };
fa1df6916   Andres Salomon   mfd: Add mfd_clon...
114
  #ifdef CONFIG_OLPC
f791be492   Bill Pemberton   mfd: remove use o...
115
  static void cs5535_clone_olpc_cells(void)
fa1df6916   Andres Salomon   mfd: Add mfd_clon...
116
  {
adfa4bd4a   Daniel Drake   mfd: OLPC: Clean ...
117
  	const char *acpi_clones[] = { "olpc-xo1-pm-acpi", "olpc-xo1-sci-acpi" };
fa1df6916   Andres Salomon   mfd: Add mfd_clon...
118
119
120
121
122
  
  	if (!machine_is_olpc())
  		return;
  
  	mfd_clone_cell("cs5535-acpi", acpi_clones, ARRAY_SIZE(acpi_clones));
fa1df6916   Andres Salomon   mfd: Add mfd_clon...
123
124
125
126
  }
  #else
  static void cs5535_clone_olpc_cells(void) { }
  #endif
f791be492   Bill Pemberton   mfd: remove use o...
127
  static int cs5535_mfd_probe(struct pci_dev *pdev,
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  		const struct pci_device_id *id)
  {
  	int err, i;
  
  	err = pci_enable_device(pdev);
  	if (err)
  		return err;
  
  	/* fill in IO range for each cell; subdrivers handle the region */
  	for (i = 0; i < ARRAY_SIZE(cs5535_mfd_cells); i++) {
  		int bar = cs5535_mfd_cells[i].id;
  		struct resource *r = &cs5535_mfd_resources[bar];
  
  		r->flags = IORESOURCE_IO;
  		r->start = pci_resource_start(pdev, bar);
  		r->end = pci_resource_end(pdev, bar);
  
  		/* id is used for temporarily storing BAR; unset it now */
  		cs5535_mfd_cells[i].id = 0;
  	}
  
  	err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells,
0848c94fb   Mark Brown   mfd: core: Push i...
150
  			      ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL);
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
151
152
153
154
155
  	if (err) {
  		dev_err(&pdev->dev, "MFD add devices failed: %d
  ", err);
  		goto err_disable;
  	}
fa1df6916   Andres Salomon   mfd: Add mfd_clon...
156
  	cs5535_clone_olpc_cells();
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
157

816b4580c   Andres Salomon   mfd: Fix cs5535 w...
158
159
  	dev_info(&pdev->dev, "%zu devices registered.
  ",
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
160
161
162
163
164
165
166
167
  			ARRAY_SIZE(cs5535_mfd_cells));
  
  	return 0;
  
  err_disable:
  	pci_disable_device(pdev);
  	return err;
  }
4740f73fe   Bill Pemberton   mfd: remove use o...
168
  static void cs5535_mfd_remove(struct pci_dev *pdev)
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
169
170
171
172
  {
  	mfd_remove_devices(&pdev->dev);
  	pci_disable_device(pdev);
  }
36fcd06c4   Jingoo Han   mfd: Remove DEFIN...
173
  static const struct pci_device_id cs5535_mfd_pci_tbl[] = {
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
174
175
176
177
178
  	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
  	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
  	{ 0, }
  };
  MODULE_DEVICE_TABLE(pci, cs5535_mfd_pci_tbl);
97e43c983   Christian Gmeiner   mfd: Fix cs5535 s...
179
  static struct pci_driver cs5535_mfd_driver = {
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
180
181
182
  	.name = DRV_NAME,
  	.id_table = cs5535_mfd_pci_tbl,
  	.probe = cs5535_mfd_probe,
84449216b   Bill Pemberton   mfd: remove use o...
183
  	.remove = cs5535_mfd_remove,
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
184
  };
38a36f5a6   Axel Lin   mfd: Use module_p...
185
  module_pci_driver(cs5535_mfd_driver);
f71e1afdd   Andres Salomon   mfd: Add cs5535-m...
186
187
188
189
  
  MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
  MODULE_DESCRIPTION("MFD driver for CS5535/CS5536 southbridge's ISA PCI device");
  MODULE_LICENSE("GPL");