diff options
Diffstat (limited to 'drivers/net/wireless/microchip/wilc1000/spi.c')
| -rw-r--r-- | drivers/net/wireless/microchip/wilc1000/spi.c | 80 | 
1 files changed, 71 insertions, 9 deletions
| diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index 640850f989dd..2c2ed4b09efd 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -8,10 +8,13 @@  #include <linux/spi/spi.h>  #include <linux/crc7.h>  #include <linux/crc-itu-t.h> +#include <linux/gpio/consumer.h>  #include "netdev.h"  #include "cfg80211.h" +#define SPI_MODALIAS		"wilc1000_spi" +  static bool enable_crc7;	/* protect SPI commands with CRC7 */  module_param(enable_crc7, bool, 0644);  MODULE_PARM_DESC(enable_crc7, @@ -43,6 +46,10 @@ struct wilc_spi {  	bool probing_crc;	/* true if we're probing chip's CRC config */  	bool crc7_enabled;	/* true if crc7 is currently enabled */  	bool crc16_enabled;	/* true if crc16 is currently enabled */ +	struct wilc_gpios { +		struct gpio_desc *enable;	/* ENABLE GPIO or NULL */ +		struct gpio_desc *reset;	/* RESET GPIO or NULL */ +	} gpios;  };  static const struct wilc_hif_func wilc_hif_spi; @@ -99,8 +106,6 @@ static int wilc_spi_reset(struct wilc *wilc);  #define DATA_PKT_LOG_SZ				DATA_PKT_LOG_SZ_MAX  #define DATA_PKT_SZ				(1 << DATA_PKT_LOG_SZ) -#define USE_SPI_DMA				0 -  #define WILC_SPI_COMMAND_STAT_SUCCESS		0  #define WILC_GET_RESP_HDR_START(h)		(((h) >> 4) & 0xf) @@ -152,6 +157,50 @@ struct wilc_spi_special_cmd_rsp {  	u8 status;  } __packed; +static int wilc_parse_gpios(struct wilc *wilc) +{ +	struct spi_device *spi = to_spi_device(wilc->dev); +	struct wilc_spi *spi_priv = wilc->bus_data; +	struct wilc_gpios *gpios = &spi_priv->gpios; + +	/* get ENABLE pin and deassert it (if it is defined): */ +	gpios->enable = devm_gpiod_get_optional(&spi->dev, +						"enable", GPIOD_OUT_LOW); +	/* get RESET pin and assert it (if it is defined): */ +	if (gpios->enable) { +		/* if enable pin exists, reset must exist as well */ +		gpios->reset = devm_gpiod_get(&spi->dev, +					      "reset", GPIOD_OUT_HIGH); +		if (IS_ERR(gpios->reset)) { +			dev_err(&spi->dev, "missing reset gpio.\n"); +			return PTR_ERR(gpios->reset); +		} +	} else { +		gpios->reset = devm_gpiod_get_optional(&spi->dev, +						       "reset", GPIOD_OUT_HIGH); +	} +	return 0; +} + +static void wilc_wlan_power(struct wilc *wilc, bool on) +{ +	struct wilc_spi *spi_priv = wilc->bus_data; +	struct wilc_gpios *gpios = &spi_priv->gpios; + +	if (on) { +		/* assert ENABLE: */ +		gpiod_set_value(gpios->enable, 1); +		mdelay(5); +		/* deassert RESET: */ +		gpiod_set_value(gpios->reset, 0); +	} else { +		/* assert RESET: */ +		gpiod_set_value(gpios->reset, 1); +		/* deassert ENABLE: */ +		gpiod_set_value(gpios->enable, 0); +	} +} +  static int wilc_bus_probe(struct spi_device *spi)  {  	int ret; @@ -171,6 +220,10 @@ static int wilc_bus_probe(struct spi_device *spi)  	wilc->bus_data = spi_priv;  	wilc->dev_irq_num = spi->irq; +	ret = wilc_parse_gpios(wilc); +	if (ret < 0) +		goto netdev_cleanup; +  	wilc->rtc_clk = devm_clk_get_optional(&spi->dev, "rtc");  	if (IS_ERR(wilc->rtc_clk)) {  		ret = PTR_ERR(wilc->rtc_clk); @@ -190,9 +243,11 @@ free:  static int wilc_bus_remove(struct spi_device *spi)  {  	struct wilc *wilc = spi_get_drvdata(spi); +	struct wilc_spi *spi_priv = wilc->bus_data;  	clk_disable_unprepare(wilc->rtc_clk);  	wilc_netdev_cleanup(wilc); +	kfree(spi_priv);  	return 0;  } @@ -203,11 +258,18 @@ static const struct of_device_id wilc_of_match[] = {  };  MODULE_DEVICE_TABLE(of, wilc_of_match); +static const struct spi_device_id wilc_spi_id[] = { +	{ "wilc1000", 0 }, +	{ /* sentinel */ } +}; +MODULE_DEVICE_TABLE(spi, wilc_spi_id); +  static struct spi_driver wilc_spi_driver = {  	.driver = { -		.name = MODALIAS, +		.name = SPI_MODALIAS,  		.of_match_table = wilc_of_match,  	}, +	.id_table = wilc_spi_id,  	.probe =  wilc_bus_probe,  	.remove = wilc_bus_remove,  }; @@ -240,7 +302,6 @@ static int wilc_spi_tx(struct wilc *wilc, u8 *b, u32 len)  		memset(&msg, 0, sizeof(msg));  		spi_message_init(&msg);  		msg.spi = spi; -		msg.is_dma_mapped = USE_SPI_DMA;  		spi_message_add_tail(&tr, &msg);  		ret = spi_sync(spi, &msg); @@ -284,7 +345,6 @@ static int wilc_spi_rx(struct wilc *wilc, u8 *rb, u32 rlen)  		memset(&msg, 0, sizeof(msg));  		spi_message_init(&msg);  		msg.spi = spi; -		msg.is_dma_mapped = USE_SPI_DMA;  		spi_message_add_tail(&tr, &msg);  		ret = spi_sync(spi, &msg); @@ -323,7 +383,6 @@ static int wilc_spi_tx_rx(struct wilc *wilc, u8 *wb, u8 *rb, u32 rlen)  		memset(&msg, 0, sizeof(msg));  		spi_message_init(&msg);  		msg.spi = spi; -		msg.is_dma_mapped = USE_SPI_DMA;  		spi_message_add_tail(&tr, &msg);  		ret = spi_sync(spi, &msg); @@ -977,9 +1036,10 @@ static int wilc_spi_reset(struct wilc *wilc)  static int wilc_spi_deinit(struct wilc *wilc)  { -	/* -	 * TODO: -	 */ +	struct wilc_spi *spi_priv = wilc->bus_data; + +	spi_priv->isinit = false; +	wilc_wlan_power(wilc, false);  	return 0;  } @@ -1000,6 +1060,8 @@ static int wilc_spi_init(struct wilc *wilc, bool resume)  		dev_err(&spi->dev, "Fail cmd read chip id...\n");  	} +	wilc_wlan_power(wilc, true); +  	/*  	 * configure protocol  	 */ |