Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 097e296d authored by Russell King - ARM Linux's avatar Russell King - ARM Linux Committed by Dominik Brodowski
Browse files

PCMCIA: soc_common: provide single socket add/remove functionality



Factor out the functionality for adding and removing a single
socket, thereby allowing SoCs to individually register each
socket.  The advantage of this approach is that SoCs can then
extend soc_pcmcia_socket as they wish.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent 0f767de6
Loading
Loading
Loading
Loading
+123 −107
Original line number Original line Diff line number Diff line
@@ -574,7 +574,7 @@ void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt,
EXPORT_SYMBOL(soc_pcmcia_enable_irqs);
EXPORT_SYMBOL(soc_pcmcia_enable_irqs);




LIST_HEAD(soc_pcmcia_sockets);
static LIST_HEAD(soc_pcmcia_sockets);
static DEFINE_MUTEX(soc_pcmcia_sockets_lock);
static DEFINE_MUTEX(soc_pcmcia_sockets_lock);


#ifdef CONFIG_CPU_FREQ
#ifdef CONFIG_CPU_FREQ
@@ -619,32 +619,40 @@ module_exit(soc_pcmcia_cpufreq_unregister);


#endif
#endif


int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops,
void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
				struct skt_dev_info *sinfo)
{
{
	struct soc_pcmcia_socket *skt;
	int ret, i;

	mutex_lock(&soc_pcmcia_sockets_lock);
	mutex_lock(&soc_pcmcia_sockets_lock);
	del_timer_sync(&skt->poll_timer);


	/*
	pcmcia_unregister_socket(&skt->socket);
	 * Initialise the per-socket structure.
	 */
	for (i = 0; i < sinfo->nskt; i++) {
		skt = &sinfo->skt[i];


		skt->socket.ops = &soc_common_pcmcia_operations;
	flush_scheduled_work();
		skt->socket.owner = ops->owner;

		skt->socket.dev.parent = dev;
	skt->ops->hw_shutdown(skt);

	soc_common_pcmcia_config_skt(skt, &dead_socket);

	list_del(&skt->node);
	mutex_unlock(&soc_pcmcia_sockets_lock);

	iounmap(skt->virt_io);
	skt->virt_io = NULL;
	release_resource(&skt->res_attr);
	release_resource(&skt->res_mem);
	release_resource(&skt->res_io);
	release_resource(&skt->res_skt);
}
EXPORT_SYMBOL(soc_pcmcia_remove_one);

int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
{
	int ret;


	init_timer(&skt->poll_timer);
	init_timer(&skt->poll_timer);
	skt->poll_timer.function = soc_common_pcmcia_poll_event;
	skt->poll_timer.function = soc_common_pcmcia_poll_event;
	skt->poll_timer.data = (unsigned long)skt;
	skt->poll_timer.data = (unsigned long)skt;
	skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD;
	skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD;


		skt->dev	= dev;
		skt->ops	= ops;

	ret = request_resource(&iomem_resource, &skt->res_skt);
	ret = request_resource(&iomem_resource, &skt->res_skt);
	if (ret)
	if (ret)
		goto out_err_1;
		goto out_err_1;
@@ -667,6 +675,8 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
		goto out_err_5;
		goto out_err_5;
	}
	}


	mutex_lock(&soc_pcmcia_sockets_lock);

	list_add(&skt->node, &soc_pcmcia_sockets);
	list_add(&skt->node, &soc_pcmcia_sockets);


	/*
	/*
@@ -674,12 +684,13 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
	 * we are not guaranteed to see a SetIOMap operation at
	 * we are not guaranteed to see a SetIOMap operation at
	 * runtime.
	 * runtime.
	 */
	 */
		ops->set_timing(skt);
	skt->ops->set_timing(skt);


		ret = ops->hw_init(skt);
	ret = skt->ops->hw_init(skt);
	if (ret)
	if (ret)
		goto out_err_6;
		goto out_err_6;


	skt->socket.ops = &soc_common_pcmcia_operations;
	skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;
	skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;
	skt->socket.resource_ops = &pccard_static_ops;
	skt->socket.resource_ops = &pccard_static_ops;
	skt->socket.irq_mask = 0;
	skt->socket.irq_mask = 0;
@@ -693,33 +704,28 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
	if (ret)
	if (ret)
		goto out_err_7;
		goto out_err_7;


		WARN_ON(skt->socket.sock != i);

	add_timer(&skt->poll_timer);
	add_timer(&skt->poll_timer);


	mutex_unlock(&soc_pcmcia_sockets_lock);

	ret = device_create_file(&skt->socket.dev, &dev_attr_status);
	ret = device_create_file(&skt->socket.dev, &dev_attr_status);
	if (ret)
	if (ret)
		goto out_err_8;
		goto out_err_8;
	}


	dev_set_drvdata(dev, sinfo);
	return ret;
	ret = 0;
	goto out;

	do {
		skt = &sinfo->skt[i];


		device_remove_file(&skt->socket.dev, &dev_attr_status);
 out_err_8:
 out_err_8:
	mutex_lock(&soc_pcmcia_sockets_lock);
	del_timer_sync(&skt->poll_timer);
	del_timer_sync(&skt->poll_timer);
	pcmcia_unregister_socket(&skt->socket);
	pcmcia_unregister_socket(&skt->socket);


 out_err_7:
 out_err_7:
	flush_scheduled_work();
	flush_scheduled_work();


		ops->hw_shutdown(skt);
	skt->ops->hw_shutdown(skt);
 out_err_6:
 out_err_6:
	list_del(&skt->node);
	list_del(&skt->node);
	mutex_unlock(&soc_pcmcia_sockets_lock);
	iounmap(skt->virt_io);
	iounmap(skt->virt_io);
 out_err_5:
 out_err_5:
	release_resource(&skt->res_attr);
	release_resource(&skt->res_attr);
@@ -730,13 +736,44 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
 out_err_2:
 out_err_2:
	release_resource(&skt->res_skt);
	release_resource(&skt->res_skt);
 out_err_1:
 out_err_1:
		i--;
	} while (i > 0);


	return ret;
}
EXPORT_SYMBOL(soc_pcmcia_add_one);

int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops,
				struct skt_dev_info *sinfo)
{
	struct soc_pcmcia_socket *skt;
	int ret, i;

	/*
	 * Initialise the per-socket structure.
	 */
	for (i = ret = 0; i < sinfo->nskt; i++) {
		skt = &sinfo->skt[i];

		skt->socket.owner = ops->owner;
		skt->socket.dev.parent = dev;

		skt->dev	= dev;
		skt->ops	= ops;

		ret = soc_pcmcia_add_one(skt);
		if (ret)
			break;

		WARN_ON(skt->socket.sock != i);
	}

	if (ret) {
		while (--i >= 0)
			soc_pcmcia_remove_one(&sinfo->skt[i]);
		kfree(sinfo);
		kfree(sinfo);
	} else {
		dev_set_drvdata(dev, sinfo);
	}


 out:
	mutex_unlock(&soc_pcmcia_sockets_lock);
	return ret;
	return ret;
}
}
EXPORT_SYMBOL(soc_common_drv_pcmcia_probe);
EXPORT_SYMBOL(soc_common_drv_pcmcia_probe);
@@ -748,29 +785,8 @@ int soc_common_drv_pcmcia_remove(struct device *dev)


	dev_set_drvdata(dev, NULL);
	dev_set_drvdata(dev, NULL);


	mutex_lock(&soc_pcmcia_sockets_lock);
	for (i = 0; i < sinfo->nskt; i++)
	for (i = 0; i < sinfo->nskt; i++) {
		soc_pcmcia_remove_one(&sinfo->skt[i]);
		struct soc_pcmcia_socket *skt = &sinfo->skt[i];

		del_timer_sync(&skt->poll_timer);

		pcmcia_unregister_socket(&skt->socket);

		flush_scheduled_work();

		skt->ops->hw_shutdown(skt);

		soc_common_pcmcia_config_skt(skt, &dead_socket);

		list_del(&skt->node);
		iounmap(skt->virt_io);
		skt->virt_io = NULL;
		release_resource(&skt->res_attr);
		release_resource(&skt->res_mem);
		release_resource(&skt->res_io);
		release_resource(&skt->res_skt);
	}
	mutex_unlock(&soc_pcmcia_sockets_lock);


	kfree(sinfo);
	kfree(sinfo);


+2 −1
Original line number Original line Diff line number Diff line
@@ -135,7 +135,8 @@ extern void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_
extern void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *, struct soc_pcmcia_timing *);
extern void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *, struct soc_pcmcia_timing *);




extern struct list_head soc_pcmcia_sockets;
void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt);
int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt);


extern int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, struct skt_dev_info *sinfo);
extern int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, struct skt_dev_info *sinfo);
extern int soc_common_drv_pcmcia_remove(struct device *dev);
extern int soc_common_drv_pcmcia_remove(struct device *dev);