Re: [PATCH v5] ARM/mmc: Convert old mmci-omap to GPIO descriptors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, May 17, 2023 at 11:35:38PM +0200, Linus Walleij wrote:
> A recent change to the OMAP driver making it use a dynamic GPIO
> base created problems with some old OMAP1 board files, among
> them Nokia 770, SX1 and also the OMAP2 Nokia n8x0.
> 
> Fix up all instances of GPIOs being used for the MMC driver
> by pushing the handling of power, slot selection and MMC
> "cover" into the driver as optional GPIOs.

OMAP2 and N8x0 uses DT, so could the GPIO table data pushed there instead
of the board file?

A.

> This is maybe not the most perfect solution as the MMC
> framework have some central handlers for some of the
> stuff, but it at least makes the situtation better and
> solves the immediate issue.
> 
> Fixes: 92bf78b33b0b ("gpio: omap: use dynamic allocation of base")
> Acked-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx>
> Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxx>
> ---
> ChangeLog v4->v5:
> - Fix the OMAP1 device name to mmci-omap.1 instead of just
>   mmci-omap.
> - Fix the OMAP2 device name to mmci-omap.0 instead of just
>   mmci-omap.
> ---
>  arch/arm/mach-omap1/board-nokia770.c   | 43 ++++---------
>  arch/arm/mach-omap1/board-sx1-mmc.c    |  1 -
>  arch/arm/mach-omap2/board-n8x0.c       | 85 ++++++++------------------
>  drivers/mmc/host/omap.c                | 46 +++++++++++++-
>  include/linux/platform_data/mmc-omap.h |  2 -
>  5 files changed, 83 insertions(+), 94 deletions(-)
> 
> diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
> index dde74694cb4c..9583417f5bea 100644
> --- a/arch/arm/mach-omap1/board-nokia770.c
> +++ b/arch/arm/mach-omap1/board-nokia770.c
> @@ -184,27 +184,23 @@ static struct omap_usb_config nokia770_usb_config __initdata = {
>  
>  #if IS_ENABLED(CONFIG_MMC_OMAP)
>  
> -#define NOKIA770_GPIO_MMC_POWER		41
> -#define NOKIA770_GPIO_MMC_SWITCH	23
> -
> -static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on,
> -				int vdd)
> -{
> -	gpio_set_value(NOKIA770_GPIO_MMC_POWER, power_on);
> -	return 0;
> -}
> -
> -static int nokia770_mmc_get_cover_state(struct device *dev, int slot)
> -{
> -	return gpio_get_value(NOKIA770_GPIO_MMC_SWITCH);
> -}
> +static struct gpiod_lookup_table nokia770_mmc_gpio_table = {
> +	.dev_id = "mmci-omap.1",
> +	.table = {
> +		/* Slot index 0, VSD power, GPIO 41 */
> +		GPIO_LOOKUP_IDX("gpio-32-47", 9,
> +				"vsd", 0, GPIO_ACTIVE_HIGH),
> +		/* Slot index 0, switch, GPIO 23 */
> +		GPIO_LOOKUP_IDX("gpio-16-31", 7,
> +				"cover", 0, GPIO_ACTIVE_HIGH),
> +		{ }
> +	},
> +};
>  
>  static struct omap_mmc_platform_data nokia770_mmc2_data = {
>  	.nr_slots                       = 1,
>  	.max_freq                       = 12000000,
>  	.slots[0]       = {
> -		.set_power		= nokia770_mmc_set_power,
> -		.get_cover_state	= nokia770_mmc_get_cover_state,
>  		.ocr_mask               = MMC_VDD_32_33|MMC_VDD_33_34,
>  		.name                   = "mmcblk",
>  	},
> @@ -214,20 +210,7 @@ static struct omap_mmc_platform_data *nokia770_mmc_data[OMAP16XX_NR_MMC];
>  
>  static void __init nokia770_mmc_init(void)
>  {
> -	int ret;
> -
> -	ret = gpio_request(NOKIA770_GPIO_MMC_POWER, "MMC power");
> -	if (ret < 0)
> -		return;
> -	gpio_direction_output(NOKIA770_GPIO_MMC_POWER, 0);
> -
> -	ret = gpio_request(NOKIA770_GPIO_MMC_SWITCH, "MMC cover");
> -	if (ret < 0) {
> -		gpio_free(NOKIA770_GPIO_MMC_POWER);
> -		return;
> -	}
> -	gpio_direction_input(NOKIA770_GPIO_MMC_SWITCH);
> -
> +	gpiod_add_lookup_table(&nokia770_mmc_gpio_table);
>  	/* Only the second MMC controller is used */
>  	nokia770_mmc_data[1] = &nokia770_mmc2_data;
>  	omap1_init_mmc(nokia770_mmc_data, OMAP16XX_NR_MMC);
> diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c
> index f1c160924dfe..f183a8448a7b 100644
> --- a/arch/arm/mach-omap1/board-sx1-mmc.c
> +++ b/arch/arm/mach-omap1/board-sx1-mmc.c
> @@ -9,7 +9,6 @@
>   * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
>   */
>  
> -#include <linux/gpio.h>
>  #include <linux/platform_device.h>
>  
>  #include "hardware.h"
> diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
> index 3353b0a923d9..50b88eb23f9f 100644
> --- a/arch/arm/mach-omap2/board-n8x0.c
> +++ b/arch/arm/mach-omap2/board-n8x0.c
> @@ -11,6 +11,7 @@
>  #include <linux/clk.h>
>  #include <linux/delay.h>
>  #include <linux/gpio.h>
> +#include <linux/gpio/machine.h>
>  #include <linux/init.h>
>  #include <linux/io.h>
>  #include <linux/irq.h>
> @@ -170,22 +171,32 @@ static struct spi_board_info n800_spi_board_info[] __initdata = {
>   * GPIO23 and GPIO9		slot 2 EMMC on N810
>   *
>   */
> -#define N8X0_SLOT_SWITCH_GPIO	96
> -#define N810_EMMC_VSD_GPIO	23
> -#define N810_EMMC_VIO_GPIO	9
> -
>  static int slot1_cover_open;
>  static int slot2_cover_open;
>  static struct device *mmc_device;
>  
> -static int n8x0_mmc_switch_slot(struct device *dev, int slot)
> -{
> -#ifdef CONFIG_MMC_DEBUG
> -	dev_dbg(dev, "Choose slot %d\n", slot + 1);
> -#endif
> -	gpio_set_value(N8X0_SLOT_SWITCH_GPIO, slot);
> -	return 0;
> -}
> +static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = {
> +	.dev_id = "mmci-omap.0",
> +	.table = {
> +		/* Slot switch, GPIO 96 */
> +		GPIO_LOOKUP("gpio-80-111", 16,
> +			    "switch", GPIO_ACTIVE_HIGH),
> +		{ }
> +	},
> +};
> +
> +static struct gpiod_lookup_table nokia810_mmc_gpio_table = {
> +	.dev_id = "mmci-omap.0",
> +	.table = {
> +		/* Slot index 1, VSD power, GPIO 23 */
> +		GPIO_LOOKUP_IDX("gpio-16-31", 7,
> +				"vsd", 1, GPIO_ACTIVE_HIGH),
> +		/* Slot index 1, VIO power, GPIO 9 */
> +		GPIO_LOOKUP_IDX("gpio-0-15", 9,
> +				"vsd", 1, GPIO_ACTIVE_HIGH),
> +		{ }
> +	},
> +};
>  
>  static int n8x0_mmc_set_power_menelaus(struct device *dev, int slot,
>  					int power_on, int vdd)
> @@ -256,31 +267,13 @@ static int n8x0_mmc_set_power_menelaus(struct device *dev, int slot,
>  	return 0;
>  }
>  
> -static void n810_set_power_emmc(struct device *dev,
> -					 int power_on)
> -{
> -	dev_dbg(dev, "Set EMMC power %s\n", power_on ? "on" : "off");
> -
> -	if (power_on) {
> -		gpio_set_value(N810_EMMC_VSD_GPIO, 1);
> -		msleep(1);
> -		gpio_set_value(N810_EMMC_VIO_GPIO, 1);
> -		msleep(1);
> -	} else {
> -		gpio_set_value(N810_EMMC_VIO_GPIO, 0);
> -		msleep(50);
> -		gpio_set_value(N810_EMMC_VSD_GPIO, 0);
> -		msleep(50);
> -	}
> -}
> -
>  static int n8x0_mmc_set_power(struct device *dev, int slot, int power_on,
>  			      int vdd)
>  {
>  	if (board_is_n800() || slot == 0)
>  		return n8x0_mmc_set_power_menelaus(dev, slot, power_on, vdd);
>  
> -	n810_set_power_emmc(dev, power_on);
> +	/* The n810 power will be handled by GPIO code in the driver */
>  
>  	return 0;
>  }
> @@ -418,13 +411,6 @@ static void n8x0_mmc_shutdown(struct device *dev)
>  static void n8x0_mmc_cleanup(struct device *dev)
>  {
>  	menelaus_unregister_mmc_callback();
> -
> -	gpio_free(N8X0_SLOT_SWITCH_GPIO);
> -
> -	if (board_is_n810()) {
> -		gpio_free(N810_EMMC_VSD_GPIO);
> -		gpio_free(N810_EMMC_VIO_GPIO);
> -	}
>  }
>  
>  /*
> @@ -433,7 +419,6 @@ static void n8x0_mmc_cleanup(struct device *dev)
>   */
>  static struct omap_mmc_platform_data mmc1_data = {
>  	.nr_slots			= 0,
> -	.switch_slot			= n8x0_mmc_switch_slot,
>  	.init				= n8x0_mmc_late_init,
>  	.cleanup			= n8x0_mmc_cleanup,
>  	.shutdown			= n8x0_mmc_shutdown,
> @@ -463,14 +448,9 @@ static struct omap_mmc_platform_data mmc1_data = {
>  
>  static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC];
>  
> -static struct gpio n810_emmc_gpios[] __initdata = {
> -	{ N810_EMMC_VSD_GPIO, GPIOF_OUT_INIT_LOW,  "MMC slot 2 Vddf" },
> -	{ N810_EMMC_VIO_GPIO, GPIOF_OUT_INIT_LOW,  "MMC slot 2 Vdd"  },
> -};
> -
>  static void __init n8x0_mmc_init(void)
>  {
> -	int err;
> +	gpiod_add_lookup_table(&nokia8xx_mmc_gpio_table);
>  
>  	if (board_is_n810()) {
>  		mmc1_data.slots[0].name = "external";
> @@ -483,20 +463,7 @@ static void __init n8x0_mmc_init(void)
>  		 */
>  		mmc1_data.slots[1].name = "internal";
>  		mmc1_data.slots[1].ban_openended = 1;
> -	}
> -
> -	err = gpio_request_one(N8X0_SLOT_SWITCH_GPIO, GPIOF_OUT_INIT_LOW,
> -			       "MMC slot switch");
> -	if (err)
> -		return;
> -
> -	if (board_is_n810()) {
> -		err = gpio_request_array(n810_emmc_gpios,
> -					 ARRAY_SIZE(n810_emmc_gpios));
> -		if (err) {
> -			gpio_free(N8X0_SLOT_SWITCH_GPIO);
> -			return;
> -		}
> +		gpiod_add_lookup_table(&nokia810_mmc_gpio_table);
>  	}
>  
>  	mmc1_data.nr_slots = 2;
> diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
> index ce78edfb402b..a14af21f12da 100644
> --- a/drivers/mmc/host/omap.c
> +++ b/drivers/mmc/host/omap.c
> @@ -26,6 +26,7 @@
>  #include <linux/clk.h>
>  #include <linux/scatterlist.h>
>  #include <linux/slab.h>
> +#include <linux/gpio/consumer.h>
>  #include <linux/platform_data/mmc-omap.h>
>  
>  
> @@ -111,6 +112,9 @@ struct mmc_omap_slot {
>  	struct mmc_request      *mrq;
>  	struct mmc_omap_host    *host;
>  	struct mmc_host		*mmc;
> +	struct gpio_desc	*vsd;
> +	struct gpio_desc	*vio;
> +	struct gpio_desc	*cover;
>  	struct omap_mmc_slot_data *pdata;
>  };
>  
> @@ -133,6 +137,7 @@ struct mmc_omap_host {
>  	int			irq;
>  	unsigned char		bus_mode;
>  	unsigned int		reg_shift;
> +	struct gpio_desc	*slot_switch;
>  
>  	struct work_struct	cmd_abort_work;
>  	unsigned		abort:1;
> @@ -216,8 +221,13 @@ static void mmc_omap_select_slot(struct mmc_omap_slot *slot, int claimed)
>  
>  	if (host->current_slot != slot) {
>  		OMAP_MMC_WRITE(host, CON, slot->saved_con & 0xFC00);
> -		if (host->pdata->switch_slot != NULL)
> -			host->pdata->switch_slot(mmc_dev(slot->mmc), slot->id);
> +		if (host->slot_switch)
> +			/*
> +			 * With two slots and a simple GPIO switch, setting
> +			 * the GPIO to 0 selects slot ID 0, setting it to 1
> +			 * selects slot ID 1.
> +			 */
> +			gpiod_set_value(host->slot_switch, slot->id);
>  		host->current_slot = slot;
>  	}
>  
> @@ -297,6 +307,9 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled)
>  static inline
>  int mmc_omap_cover_is_open(struct mmc_omap_slot *slot)
>  {
> +	/* If we have a GPIO then use that */
> +	if (slot->cover)
> +		return gpiod_get_value(slot->cover);
>  	if (slot->pdata->get_cover_state)
>  		return slot->pdata->get_cover_state(mmc_dev(slot->mmc),
>  						    slot->id);
> @@ -1106,6 +1119,11 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on,
>  
>  	host = slot->host;
>  
> +	if (slot->vsd)
> +		gpiod_set_value(slot->vsd, power_on);
> +	if (slot->vio)
> +		gpiod_set_value(slot->vio, power_on);
> +
>  	if (slot->pdata->set_power != NULL)
>  		slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on,
>  					vdd);
> @@ -1240,6 +1258,23 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
>  	slot->power_mode = MMC_POWER_UNDEFINED;
>  	slot->pdata = &host->pdata->slots[id];
>  
> +	/* Check for some optional GPIO controls */
> +	slot->vsd = gpiod_get_index_optional(host->dev, "vsd",
> +					     id, GPIOD_OUT_LOW);
> +	if (IS_ERR(slot->vsd))
> +		return dev_err_probe(host->dev, PTR_ERR(slot->vsd),
> +				     "error looking up VSD GPIO\n");
> +	slot->vio = gpiod_get_index_optional(host->dev, "vio",
> +					     id, GPIOD_OUT_LOW);
> +	if (IS_ERR(slot->vio))
> +		return dev_err_probe(host->dev, PTR_ERR(slot->vio),
> +				     "error looking up VIO GPIO\n");
> +	slot->cover = gpiod_get_index_optional(host->dev, "cover",
> +						id, GPIOD_IN);
> +	if (IS_ERR(slot->cover))
> +		return dev_err_probe(host->dev, PTR_ERR(slot->cover),
> +				     "error looking up cover switch GPIO\n");
> +
>  	host->slots[id] = slot;
>  
>  	mmc->caps = 0;
> @@ -1349,6 +1384,13 @@ static int mmc_omap_probe(struct platform_device *pdev)
>  	if (IS_ERR(host->virt_base))
>  		return PTR_ERR(host->virt_base);
>  
> +	host->slot_switch = gpiod_get_optional(host->dev, "switch",
> +					       GPIOD_OUT_LOW);
> +	if (IS_ERR(host->slot_switch))
> +		return dev_err_probe(host->dev, PTR_ERR(host->slot_switch),
> +				     "error looking up slot switch GPIO\n");
> +
> +
>  	INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work);
>  	INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work);
>  
> diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h
> index 91051e9907f3..054d0c3c5ec5 100644
> --- a/include/linux/platform_data/mmc-omap.h
> +++ b/include/linux/platform_data/mmc-omap.h
> @@ -20,8 +20,6 @@ struct omap_mmc_platform_data {
>  	 * maximum frequency on the MMC bus */
>  	unsigned int max_freq;
>  
> -	/* switch the bus to a new slot */
> -	int (*switch_slot)(struct device *dev, int slot);
>  	/* initialize board-specific MMC functionality, can be NULL if
>  	 * not supported */
>  	int (*init)(struct device *dev);
> -- 
> 2.34.1
> 



[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux