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

Commit 00b137cf authored by Russell King's avatar Russell King Committed by Russell King
Browse files

[MMC] Add MMC class devices



Create a mmc_host class to allow enumeration of MMC host controllers
even though they have no card(s) inserted.

Patch based on work by Pierre Ossman.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent d366b643
Loading
Loading
Loading
Loading
+10 −13
Original line number Diff line number Diff line
@@ -796,17 +796,13 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{
	struct mmc_host *host;

	host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
	host = mmc_alloc_host_sysfs(extra, dev);
	if (host) {
		memset(host, 0, sizeof(struct mmc_host) + extra);

		spin_lock_init(&host->lock);
		init_waitqueue_head(&host->wq);
		INIT_LIST_HEAD(&host->cards);
		INIT_WORK(&host->detect, mmc_rescan, host);

		host->dev = dev;

		/*
		 * By default, hosts do not support SGIO or large requests.
		 * They have to set these according to their abilities.
@@ -828,15 +824,15 @@ EXPORT_SYMBOL(mmc_alloc_host);
 */
int mmc_add_host(struct mmc_host *host)
{
	static unsigned int host_num;

	snprintf(host->host_name, sizeof(host->host_name),
		 "mmc%d", host_num++);
	int ret;

	ret = mmc_add_host_sysfs(host);
	if (ret == 0) {
		mmc_power_off(host);
		mmc_detect_change(host);
	}

	return 0;
	return ret;
}

EXPORT_SYMBOL(mmc_add_host);
@@ -859,6 +855,7 @@ void mmc_remove_host(struct mmc_host *host)
	}

	mmc_power_off(host);
	mmc_remove_host_sysfs(host);
}

EXPORT_SYMBOL(mmc_remove_host);
@@ -872,7 +869,7 @@ EXPORT_SYMBOL(mmc_remove_host);
void mmc_free_host(struct mmc_host *host)
{
	flush_scheduled_work();
	kfree(host);
	mmc_free_host_sysfs(host);
}

EXPORT_SYMBOL(mmc_free_host);
+5 −0
Original line number Diff line number Diff line
@@ -13,4 +13,9 @@
void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
int mmc_register_card(struct mmc_card *card);
void mmc_remove_card(struct mmc_card *card);

struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
int mmc_add_host_sysfs(struct mmc_host *host);
void mmc_remove_host_sysfs(struct mmc_host *host);
void mmc_free_host_sysfs(struct mmc_host *host);
#endif
+71 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#define dev_to_mmc_card(d)	container_of(d, struct mmc_card, dev)
#define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
#define cls_dev_to_mmc_host(d)	container_of(d, struct mmc_host, class_dev)

#define MMC_ATTR(name, fmt, args...)					\
static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)	\
@@ -224,13 +225,82 @@ void mmc_remove_card(struct mmc_card *card)
}


static void mmc_host_classdev_release(struct class_device *dev)
{
	struct mmc_host *host = cls_dev_to_mmc_host(dev);
	kfree(host);
}

static struct class mmc_host_class = {
	.name		= "mmc_host",
	.release	= mmc_host_classdev_release,
};

/*
 * Internal function. Allocate a new MMC host.
 */
struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
{
	struct mmc_host *host;

	host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
	if (host) {
		memset(host, 0, sizeof(struct mmc_host) + extra);

		host->dev = dev;
		host->class_dev.dev = host->dev;
		host->class_dev.class = &mmc_host_class;
		class_device_initialize(&host->class_dev);
	}

	return host;
}

/*
 * Internal function. Register a new MMC host with the MMC class.
 */
int mmc_add_host_sysfs(struct mmc_host *host)
{
	static unsigned int host_num;

	snprintf(host->host_name, sizeof(host->host_name),
		 "mmc%d", host_num++);

	strlcpy(host->class_dev.class_id, host->host_name, BUS_ID_SIZE);
	return class_device_add(&host->class_dev);
}

/*
 * Internal function. Unregister a MMC host with the MMC class.
 */
void mmc_remove_host_sysfs(struct mmc_host *host)
{
	class_device_del(&host->class_dev);
}

/*
 * Internal function. Free a MMC host.
 */
void mmc_free_host_sysfs(struct mmc_host *host)
{
	class_device_put(&host->class_dev);
}


static int __init mmc_init(void)
{
	return bus_register(&mmc_bus_type);
	int ret = bus_register(&mmc_bus_type);
	if (ret == 0) {
		ret = class_register(&mmc_host_class);
		if (ret)
			bus_unregister(&mmc_bus_type);
	}
	return ret;
}

static void __exit mmc_exit(void)
{
	class_unregister(&mmc_host_class);
	bus_unregister(&mmc_bus_type);
}

+1 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ struct device;

struct mmc_host {
	struct device		*dev;
	struct class_device	class_dev;
	struct mmc_host_ops	*ops;
	unsigned int		f_min;
	unsigned int		f_max;