Blame view

drivers/pcmcia/sa1100_generic.c 5.89 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  /*======================================================================
  
      Device driver for the PCMCIA control functionality of StrongARM
      SA-1100 microprocessors.
  
      The contents of this file are subject to the Mozilla Public
      License Version 1.1 (the "License"); you may not use this file
      except in compliance with the License. You may obtain a copy of
      the License at http://www.mozilla.org/MPL/
  
      Software distributed under the License is distributed on an "AS
      IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
      implied. See the License for the specific language governing
      rights and limitations under the License.
  
      The initial developer of the original code is John G. Dorsey
      <john+@cs.cmu.edu>.  Portions created by John G. Dorsey are
      Copyright (C) 1999 John G. Dorsey.  All Rights Reserved.
  
      Alternatively, the contents of this file may be used under the
      terms of the GNU Public License version 2 (the "GPL"), in which
      case the provisions of the GPL are applicable instead of the
      above.  If you wish to allow the use of your version of this file
      only under the terms of the GPL and not to allow others to use
      your version of this file under the MPL, indicate your decision
      by deleting the provisions above and replace them with the notice
      and other provisions required by the GPL.  If you do not delete
      the provisions above, a recipient may use your version of this
      file under either the MPL or the GPL.
      
  ======================================================================*/
  
  #include <linux/module.h>
7be893aa2   Russell King   pcmcia: sa1100: p...
34
  #include <linux/gpio/consumer.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  #include <linux/init.h>
7be893aa2   Russell King   pcmcia: sa1100: p...
36
  #include <linux/regulator/consumer.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
37
  #include <linux/slab.h>
d052d1bef   Russell King   Create platform_d...
38
  #include <linux/platform_device.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #include <pcmcia/ss.h>
77bb86a1b   Pavel Machek   [ARM] Support pcm...
41
  #include <asm/hardware/scoop.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  #include "sa1100_generic.h"
7be893aa2   Russell King   pcmcia: sa1100: p...
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  static const char *sa11x0_cf_gpio_names[] = {
  	[SOC_STAT_CD] = "detect",
  	[SOC_STAT_BVD1] = "bvd1",
  	[SOC_STAT_BVD2] = "bvd2",
  	[SOC_STAT_RDY] = "ready",
  };
  
  static int sa11x0_cf_hw_init(struct soc_pcmcia_socket *skt)
  {
  	struct device *dev = skt->socket.dev.parent;
  	int i;
  
  	skt->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
  	if (IS_ERR(skt->gpio_reset))
  		return PTR_ERR(skt->gpio_reset);
  
  	skt->gpio_bus_enable = devm_gpiod_get_optional(dev, "bus-enable",
  						       GPIOD_OUT_HIGH);
  	if (IS_ERR(skt->gpio_bus_enable))
  		return PTR_ERR(skt->gpio_bus_enable);
  
  	skt->vcc.reg = devm_regulator_get_optional(dev, "vcc");
  	if (IS_ERR(skt->vcc.reg))
  		return PTR_ERR(skt->vcc.reg);
  
  	if (!skt->vcc.reg)
  		dev_warn(dev,
  			 "no Vcc regulator provided, ignoring Vcc controls
  ");
  
  	for (i = 0; i < ARRAY_SIZE(sa11x0_cf_gpio_names); i++) {
  		skt->stat[i].name = sa11x0_cf_gpio_names[i];
  		skt->stat[i].desc = devm_gpiod_get_optional(dev,
  					sa11x0_cf_gpio_names[i], GPIOD_IN);
  		if (IS_ERR(skt->stat[i].desc))
  			return PTR_ERR(skt->stat[i].desc);
  	}
  	return 0;
  }
  
  static int sa11x0_cf_configure_socket(struct soc_pcmcia_socket *skt,
  	const socket_state_t *state)
  {
  	return soc_pcmcia_regulator_set(skt, &skt->vcc, state->Vcc);
  }
  
  static struct pcmcia_low_level sa11x0_cf_ops = {
  	.owner = THIS_MODULE,
  	.hw_init = sa11x0_cf_hw_init,
  	.socket_state = soc_common_cf_socket_state,
  	.configure_socket = sa11x0_cf_configure_socket,
  };
77bb86a1b   Pavel Machek   [ARM] Support pcm...
95
  int __init pcmcia_collie_init(struct device *dev);
7be893aa2   Russell King   pcmcia: sa1100: p...
96
  static int (*sa11x0_pcmcia_legacy_hw_init[])(struct device *dev) = {
e7435f866   Dmitry Artamonow   ARM: 5824/1: SA11...
97
  #if defined(CONFIG_SA1100_H3100) || defined(CONFIG_SA1100_H3600)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
  	pcmcia_h3600_init,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
  #ifdef CONFIG_SA1100_SIMPAD
  	pcmcia_simpad_init,
  #endif
77bb86a1b   Pavel Machek   [ARM] Support pcm...
103
104
105
  #ifdef CONFIG_SA1100_COLLIE
         pcmcia_collie_init,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
  };
7be893aa2   Russell King   pcmcia: sa1100: p...
107
  static int sa11x0_drv_pcmcia_legacy_probe(struct platform_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
110
111
112
113
  {
  	int i, ret = -ENODEV;
  
  	/*
  	 * Initialise any "on-board" PCMCIA sockets.
  	 */
7be893aa2   Russell King   pcmcia: sa1100: p...
114
115
  	for (i = 0; i < ARRAY_SIZE(sa11x0_pcmcia_legacy_hw_init); i++) {
  		ret = sa11x0_pcmcia_legacy_hw_init[i](&dev->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
119
120
121
  		if (ret == 0)
  			break;
  	}
  
  	return ret;
  }
7be893aa2   Russell King   pcmcia: sa1100: p...
122
  static int sa11x0_drv_pcmcia_legacy_remove(struct platform_device *dev)
7a192ec33   Ming Lei   platform driver: ...
123
  {
be85458ed   Russell King - ARM Linux   PCMCIA: soc_commo...
124
125
126
127
128
129
130
  	struct skt_dev_info *sinfo = platform_get_drvdata(dev);
  	int i;
  
  	platform_set_drvdata(dev, NULL);
  
  	for (i = 0; i < sinfo->nskt; i++)
  		soc_pcmcia_remove_one(&sinfo->skt[i]);
be85458ed   Russell King - ARM Linux   PCMCIA: soc_commo...
131
  	return 0;
7be893aa2   Russell King   pcmcia: sa1100: p...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  }
  
  static int sa11x0_drv_pcmcia_probe(struct platform_device *pdev)
  {
  	struct soc_pcmcia_socket *skt;
  	struct device *dev = &pdev->dev;
  
  	if (pdev->id == -1)
  		return sa11x0_drv_pcmcia_legacy_probe(pdev);
  
  	skt = devm_kzalloc(dev, sizeof(*skt), GFP_KERNEL);
  	if (!skt)
  		return -ENOMEM;
  
  	platform_set_drvdata(pdev, skt);
  
  	skt->nr = pdev->id;
  	skt->clk = devm_clk_get(dev, NULL);
  	if (IS_ERR(skt->clk))
  		return PTR_ERR(skt->clk);
  
  	sa11xx_drv_pcmcia_ops(&sa11x0_cf_ops);
  	soc_pcmcia_init_one(skt, &sa11x0_cf_ops, dev);
  
  	return sa11xx_drv_pcmcia_add_one(skt);
  }
  
  static int sa11x0_drv_pcmcia_remove(struct platform_device *dev)
  {
  	struct soc_pcmcia_socket *skt;
  
  	if (dev->id == -1)
  		return sa11x0_drv_pcmcia_legacy_remove(dev);
  
  	skt = platform_get_drvdata(dev);
  
  	soc_pcmcia_remove_one(skt);
  
  	return 0;
7a192ec33   Ming Lei   platform driver: ...
171
  }
7a192ec33   Ming Lei   platform driver: ...
172
173
174
  static struct platform_driver sa11x0_pcmcia_driver = {
  	.driver = {
  		.name		= "sa11x0-pcmcia",
7a192ec33   Ming Lei   platform driver: ...
175
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  	.probe		= sa11x0_drv_pcmcia_probe,
7a192ec33   Ming Lei   platform driver: ...
177
  	.remove		= sa11x0_drv_pcmcia_remove,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
182
183
184
185
186
187
188
189
  };
  
  /* sa11x0_pcmcia_init()
   * ^^^^^^^^^^^^^^^^^^^^
   *
   * This routine performs low-level PCMCIA initialization and then
   * registers this socket driver with Card Services.
   *
   * Returns: 0 on success, -ve error code on failure
   */
  static int __init sa11x0_pcmcia_init(void)
  {
7a192ec33   Ming Lei   platform driver: ...
190
  	return platform_driver_register(&sa11x0_pcmcia_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
193
194
195
196
197
198
199
  }
  
  /* sa11x0_pcmcia_exit()
   * ^^^^^^^^^^^^^^^^^^^^
   * Invokes the low-level kernel service to free IRQs associated with this
   * socket controller and reset GPIO edge detection.
   */
  static void __exit sa11x0_pcmcia_exit(void)
  {
7a192ec33   Ming Lei   platform driver: ...
200
  	platform_driver_unregister(&sa11x0_pcmcia_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
204
205
  }
  
  MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
  MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11x0 Socket Controller");
  MODULE_LICENSE("Dual MPL/GPL");
f36598aec   Richard Purdie   [ARM] 2873/1: PCM...
206
  fs_initcall(sa11x0_pcmcia_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  module_exit(sa11x0_pcmcia_exit);