diff mbox series

[1/2] dt-bindings: wireless: wilc1000: Document WILC3000 compatible string

Message ID 20240821184356.163816-1-marex@denx.de
State Changes Requested
Headers show
Series [1/2] dt-bindings: wireless: wilc1000: Document WILC3000 compatible string | expand

Checks

Context Check Description
robh/checkpatch success
robh/patch-applied success
robh/dtbs-check warning build log
robh/dt-meta-schema success

Commit Message

Marek Vasut Aug. 21, 2024, 6:42 p.m. UTC
Document compatible string for the WILC3000 chip. The chip is similar
to WILC1000, except that the register layout is slightly different and
it does not support WPA3/SAE.

Signed-off-by: Marek Vasut <marex@denx.de>
---
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Adham Abozaeid <adham.abozaeid@microchip.com>
Cc: Ajay Singh <ajay.kathat@microchip.com>
Cc: Alexis Lothoré <alexis.lothore@bootlin.com>
Cc: Claudiu Beznea <claudiu.beznea@tuxon.dev>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Kalle Valo <kvalo@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Marek Vasut <marex@denx.de>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Rob Herring <robh@kernel.org>
Cc: devicetree@vger.kernel.org
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
---
 .../devicetree/bindings/net/wireless/microchip,wilc1000.yaml  | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Comments

Krzysztof Kozlowski Aug. 22, 2024, 8:07 a.m. UTC | #1
On Wed, Aug 21, 2024 at 08:42:32PM +0200, Marek Vasut wrote:
> Document compatible string for the WILC3000 chip. The chip is similar
> to WILC1000, except that the register layout is slightly different and
> it does not support WPA3/SAE.
> 
> Signed-off-by: Marek Vasut <marex@denx.de>
> ---
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Adham Abozaeid <adham.abozaeid@microchip.com>
> Cc: Ajay Singh <ajay.kathat@microchip.com>
> Cc: Alexis Lothoré <alexis.lothore@bootlin.com>
> Cc: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Kalle Valo <kvalo@kernel.org>
> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
> Cc: Marek Vasut <marex@denx.de>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Rob Herring <robh@kernel.org>
> Cc: devicetree@vger.kernel.org
> Cc: linux-wireless@vger.kernel.org
> Cc: netdev@vger.kernel.org
> ---
>  .../devicetree/bindings/net/wireless/microchip,wilc1000.yaml  | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
> index 2460ccc082371..1bf3496c21e64 100644
> --- a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
> +++ b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
> @@ -16,7 +16,9 @@ description:
>  
>  properties:
>    compatible:
> -    const: microchip,wilc1000
> +    enum:
> +      - microchip,wilc1000
> +      - microchip,wilc3000

Your driver change suggests device type is fully auto-detectable, thus
they are compatible.

Best regards,
Krzysztof
Simon Horman Aug. 22, 2024, 10:26 a.m. UTC | #2
On Wed, Aug 21, 2024 at 08:42:33PM +0200, Marek Vasut wrote:
> From: Ajay Singh <ajay.kathat@microchip.com>
> 
> Add support for the WILC3000 chip. The chip is similar to WILC1000,
> except that the register layout is slightly different and it does
> not support WPA3/SAE.
> 
> Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
> Signed-off-by: Marek Vasut <marex@denx.de>

...

> diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c
> index 41122199d51eb..7b99fcc450fd3 100644
> --- a/drivers/net/wireless/microchip/wilc1000/sdio.c
> +++ b/drivers/net/wireless/microchip/wilc1000/sdio.c
> @@ -764,9 +764,13 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume)
>  	 *      make sure can read back chip id correctly
>  	 **/
>  	if (!resume) {
> -		ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid);
> -		if (ret) {
> -			dev_err(&func->dev, "Fail cmd read chip id...\n");
> +		chipid = wilc_get_chipid(wilc, true);
> +		if (is_wilc3000(chipid)) {
> +			wilc->chip = WILC_3000;
> +		} else if (is_wilc1000(chipid)) {
> +			wilc->chip = WILC_1000;
> +		} else {
> +			dev_err(&func->dev, "Unsupported chipid: %x\n", chipid);
>  			return ret;

Hi Marek and Ajay,

It seems that with this change ret will be 0 here.
Perhaps an negative error code should be returned instead?

Flagged by Smatch.

>  		}
>  		dev_err(&func->dev, "chipid (%08x)\n", chipid);

...
Alexis Lothoré Aug. 22, 2024, 12:10 p.m. UTC | #3
Hello Marek,

I was coincidentally working on adding wilc3000 support upstream too. My work is
also based on downstream tree, so my comments will likely reflect the reworks I
was doing or intended to do.
For the record, I have some wilc1000 and wilc3000 modules, in both  sdio and spi
setups.

On 8/21/24 20:42, Marek Vasut wrote:
> From: Ajay Singh <ajay.kathat@microchip.com>

[...]

>  	if (!resume) {
> -		ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid);
> -		if (ret) {
> -			dev_err(&func->dev, "Fail cmd read chip id...\n");
> +		chipid = wilc_get_chipid(wilc, true);
> +		if (is_wilc3000(chipid)) {
> +			wilc->chip = WILC_3000;
> +		} else if (is_wilc1000(chipid)) {
> +			wilc->chip = WILC_1000;
> +		} else {
> +			dev_err(&func->dev, "Unsupported chipid: %x\n", chipid);
>  			return ret;
>  		}

I wonder if this additional enum (enum wilc_chip_type)  is really useful. We
already store the raw chipid, which just needs to be masked to know about the
device type. We should likely store one or the other but not both, otherwise we
may just risk to create desync without really saving useful info.

Also, this change makes wilc1000-sdio failing to build as module (missing symbol
export on wilc_get_chipid)

[...]

> -	/* select VMM table 0 */
> -	if (val & SEL_VMM_TBL0)
> -		reg |= BIT(5);
> -	/* select VMM table 1 */
> -	if (val & SEL_VMM_TBL1)
> -		reg |= BIT(6);
> -	/* enable VMM */
> -	if (val & EN_VMM)
> -		reg |= BIT(7);
> +	if (wilc->chip == WILC_1000) {

wilc1000 should likely remain the default/fallback ?

[...]

> @@ -1232,10 +1234,7 @@ static int wilc_validate_chipid(struct wilc *wilc)
>  		dev_err(&spi->dev, "Fail cmd read chip id...\n");
>  		return ret;
>  	}
> -	if (!is_wilc1000(chipid)) {
> -		dev_err(&spi->dev, "Unknown chip id 0x%x\n", chipid);
> -		return -ENODEV;
> -	}
> +

Instead of dropping any filtering (and then making the function name become
irrelevant), why not ensuring that it is at least either a wilc1000 or a wilc3000 ?

>  	return 0;
>  }
>  
> diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c
> index 533939e71534a..a7cc8c0ea5de4 100644
> --- a/drivers/net/wireless/microchip/wilc1000/wlan.c
> +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c
> @@ -555,7 +555,7 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
>  	return rqe;
>  }

[...]

> +static int chip_allow_sleep_wilc3000(struct wilc *wilc)
> +{
> +	u32 reg = 0;
> +	int ret;
> +	const struct wilc_hif_func *hif_func = wilc->hif_func;
> +
> +	if (wilc->io_type == WILC_HIF_SDIO) {
> +		ret = hif_func->hif_read_reg(wilc, WILC_SDIO_WAKEUP_REG, &reg);
> +		if (ret)
> +			return ret;
> +		ret = hif_func->hif_write_reg(wilc, WILC_SDIO_WAKEUP_REG,
> +					      reg & ~WILC_SDIO_WAKEUP_BIT);
> +		if (ret)
> +			return ret;
> +	} else {
> +		ret = hif_func->hif_read_reg(wilc, WILC_SPI_WAKEUP_REG, &reg);
> +		if (ret)
> +			return ret;
> +		ret = hif_func->hif_write_reg(wilc, WILC_SPI_WAKEUP_REG,
> +					      reg & ~WILC_SPI_WAKEUP_BIT);
> +		if (ret)
> +			return ret;
>  	}
> +	return 0;
> +}
> +
> +void chip_allow_sleep(struct wilc *wilc)
> +{
> +	if (wilc->chip == WILC_1000)
> +		chip_allow_sleep_wilc1000(wilc);
> +	else
> +		chip_allow_sleep_wilc3000(wilc);
>  }
>  EXPORT_SYMBOL_GPL(chip_allow_sleep);
>  
> -void chip_wakeup(struct wilc *wilc)
> +static void chip_wakeup_wilc1000(struct wilc *wilc)
>  {
>  	u32 ret = 0;
>  	u32 clk_status_val = 0, trials = 0;
> @@ -627,15 +662,15 @@ void chip_wakeup(struct wilc *wilc)
>  	if (wilc->io_type == WILC_HIF_SDIO) {
>  		wakeup_reg = WILC_SDIO_WAKEUP_REG;
>  		wakeup_bit = WILC_SDIO_WAKEUP_BIT;
> -		clk_status_reg = WILC_SDIO_CLK_STATUS_REG;
> -		clk_status_bit = WILC_SDIO_CLK_STATUS_BIT;
> +		clk_status_reg = WILC1000_SDIO_CLK_STATUS_REG;
> +		clk_status_bit = WILC1000_SDIO_CLK_STATUS_BIT;
>  		from_host_to_fw_reg = WILC_SDIO_HOST_TO_FW_REG;
>  		from_host_to_fw_bit = WILC_SDIO_HOST_TO_FW_BIT;
>  	} else {
>  		wakeup_reg = WILC_SPI_WAKEUP_REG;
>  		wakeup_bit = WILC_SPI_WAKEUP_BIT;
> -		clk_status_reg = WILC_SPI_CLK_STATUS_REG;
> -		clk_status_bit = WILC_SPI_CLK_STATUS_BIT;
> +		clk_status_reg = WILC1000_SPI_CLK_STATUS_REG;
> +		clk_status_bit = WILC1000_SPI_CLK_STATUS_BIT;
>  		from_host_to_fw_reg = WILC_SPI_HOST_TO_FW_REG;
>  		from_host_to_fw_bit = WILC_SPI_HOST_TO_FW_BIT;
>  	}
> @@ -674,12 +709,80 @@ void chip_wakeup(struct wilc *wilc)
>  	if (wilc->io_type == WILC_HIF_SPI)
>  		wilc->hif_func->hif_reset(wilc);
>  }
> +
> +static void chip_wakeup_wilc3000(struct wilc *wilc)
> +{
> +	u32 wakeup_reg_val, clk_status_reg_val, trials = 0;
> +	u32 wakeup_reg, wakeup_bit;
> +	u32 clk_status_reg, clk_status_bit;
> +	int wake_seq_trials = 5;
> +	const struct wilc_hif_func *hif_func = wilc->hif_func;
> +
> +	if (wilc->io_type == WILC_HIF_SDIO) {
> +		wakeup_reg = WILC_SDIO_WAKEUP_REG;
> +		wakeup_bit = WILC_SDIO_WAKEUP_BIT;
> +		clk_status_reg = WILC3000_SDIO_CLK_STATUS_REG;
> +		clk_status_bit = WILC3000_SDIO_CLK_STATUS_BIT;
> +	} else {
> +		wakeup_reg = WILC_SPI_WAKEUP_REG;
> +		wakeup_bit = WILC_SPI_WAKEUP_BIT;
> +		clk_status_reg = WILC3000_SPI_CLK_STATUS_REG;
> +		clk_status_bit = WILC3000_SPI_CLK_STATUS_BIT;
> +	}
> +
> +	hif_func->hif_read_reg(wilc, wakeup_reg, &wakeup_reg_val);
> +	do {
> +		hif_func->hif_write_reg(wilc, wakeup_reg, wakeup_reg_val |
> +							  wakeup_bit);
> +		/* Check the clock status */
> +		hif_func->hif_read_reg(wilc, clk_status_reg,
> +				       &clk_status_reg_val);
> +
> +		/* In case of clocks off, wait 1ms, and check it again.
> +		 * if still off, wait for another 1ms, for a total wait of 3ms.
> +		 * If still off, redo the wake up sequence
> +		 */
> +		while ((clk_status_reg_val & clk_status_bit) == 0 &&
> +		       (++trials % 4) != 0) {
> +			/* Wait for the chip to stabilize*/
> +			usleep_range(1000, 1100);
> +
> +			/* Make sure chip is awake. This is an extra step that
> +			 * can be removed later to avoid the bus access
> +			 * overhead
> +			 */
> +			hif_func->hif_read_reg(wilc, clk_status_reg,
> +					       &clk_status_reg_val);
> +		}
> +		/* in case of failure, Reset the wakeup bit to introduce a new
> +		 * edge on the next loop
> +		 */
> +		if ((clk_status_reg_val & clk_status_bit) == 0) {
> +			hif_func->hif_write_reg(wilc, wakeup_reg,
> +						wakeup_reg_val & (~wakeup_bit));
> +			/* added wait before wakeup sequence retry */
> +			usleep_range(200, 300);
> +		}
> +	} while ((clk_status_reg_val & clk_status_bit) == 0 && wake_seq_trials-- > 0);
> +	if (!wake_seq_trials)
> +		dev_err(wilc->dev, "clocks still OFF. Wake up failed\n");
> +}
> +
> +void chip_wakeup(struct wilc *wilc)
> +{
> +	if (wilc->chip == WILC_1000)
> +		chip_wakeup_wilc1000(wilc);
> +	else
> +		chip_wakeup_wilc3000(wilc);
> +}
>  EXPORT_SYMBOL_GPL(chip_wakeup);

This new support makes a few places in wlan.c, netdev.c and in bus files
(sdio.c, spi.c) install (sometimes big) branches on the device type (chip init,
sleep, wakeup, read interrupt, clear interrupt, txq handling, etc), because the
registers are different, the masks are different, the number of involved
registers may not be the same, wilc3000 may need more operations to perform the
same thing... I feel like it will make it harder in the long run to maintain the
driver, especially if some new variants are added later. Those branches tend to
show that some operations in those files are too specific to the targeted
device. I was examining the possibility to start creating device-type specific
files (wilc1000.c, wilc3000.c) and move those operations as "device-specific"
ops. Then wlan/netdev would call those chip-specific ops, which in turn may call
the hif_func ops. It may need some rework in the bus files to fit this new
hierarchy, but it may allow to keep netdev and wlan unaware of the device type,
and since wilc3000 has bluetooth, it may also make it easier to introduce the
corresponding support later. What do you think about it ? Ajay, any opinion on
this ?

Thanks,

Alexis
Marek Vasut Aug. 23, 2024, 1:38 a.m. UTC | #4
On 8/22/24 10:07 AM, Krzysztof Kozlowski wrote:

Hi,

>> diff --git a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
>> index 2460ccc082371..1bf3496c21e64 100644
>> --- a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
>> +++ b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
>> @@ -16,7 +16,9 @@ description:
>>   
>>   properties:
>>     compatible:
>> -    const: microchip,wilc1000
>> +    enum:
>> +      - microchip,wilc1000
>> +      - microchip,wilc3000
> 
> Your driver change suggests device type is fully auto-detectable

It seems that way, yes.

>, thus
> they are compatible.

I _think_ the hardware is internally somewhat different, the WILC1000 is 
WiFi-only device and the WILC3000 has some extra Bluetooth part (which 
is currently not supported).

Maybe a fallback compatible string would be better here ?
Marek Vasut Aug. 23, 2024, 1:42 a.m. UTC | #5
On 8/22/24 12:26 PM, Simon Horman wrote:
> On Wed, Aug 21, 2024 at 08:42:33PM +0200, Marek Vasut wrote:
>> From: Ajay Singh <ajay.kathat@microchip.com>
>>
>> Add support for the WILC3000 chip. The chip is similar to WILC1000,
>> except that the register layout is slightly different and it does
>> not support WPA3/SAE.
>>
>> Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
>> Signed-off-by: Marek Vasut <marex@denx.de>
> 
> ...
> 
>> diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c
>> index 41122199d51eb..7b99fcc450fd3 100644
>> --- a/drivers/net/wireless/microchip/wilc1000/sdio.c
>> +++ b/drivers/net/wireless/microchip/wilc1000/sdio.c
>> @@ -764,9 +764,13 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume)
>>   	 *      make sure can read back chip id correctly
>>   	 **/
>>   	if (!resume) {
>> -		ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid);
>> -		if (ret) {
>> -			dev_err(&func->dev, "Fail cmd read chip id...\n");
>> +		chipid = wilc_get_chipid(wilc, true);
>> +		if (is_wilc3000(chipid)) {
>> +			wilc->chip = WILC_3000;
>> +		} else if (is_wilc1000(chipid)) {
>> +			wilc->chip = WILC_1000;
>> +		} else {
>> +			dev_err(&func->dev, "Unsupported chipid: %x\n", chipid);
>>   			return ret;
> 
> Hi Marek and Ajay,
> 
> It seems that with this change ret will be 0 here.
> Perhaps an negative error code should be returned instead?

Fixed by returning -EINVAL , thanks .
Marek Vasut Aug. 23, 2024, 2:46 a.m. UTC | #6
On 8/22/24 2:10 PM, Alexis Lothoré wrote:
> Hello Marek,

Hi,

> I was coincidentally working on adding wilc3000 support upstream too.

I hope you weren't too far along with that and I didn't waste too much 
of your time/effort here.

> My work is
> also based on downstream tree, so my comments will likely reflect the reworks I
> was doing or intended to do.
> For the record, I have some wilc1000 and wilc3000 modules, in both  sdio and spi
> setups.

Nice, I only have this WILC3000 SDIO device .

> On 8/21/24 20:42, Marek Vasut wrote:
>> From: Ajay Singh <ajay.kathat@microchip.com>
> 
> [...]
> 
>>   	if (!resume) {
>> -		ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid);
>> -		if (ret) {
>> -			dev_err(&func->dev, "Fail cmd read chip id...\n");
>> +		chipid = wilc_get_chipid(wilc, true);
>> +		if (is_wilc3000(chipid)) {
>> +			wilc->chip = WILC_3000;
>> +		} else if (is_wilc1000(chipid)) {
>> +			wilc->chip = WILC_1000;
>> +		} else {
>> +			dev_err(&func->dev, "Unsupported chipid: %x\n", chipid);
>>   			return ret;
>>   		}
> 
> I wonder if this additional enum (enum wilc_chip_type)  is really useful. We
> already store the raw chipid, which just needs to be masked to know about the
> device type. We should likely store one or the other but not both, otherwise we
> may just risk to create desync without really saving useful info.
> 
> Also, this change makes wilc1000-sdio failing to build as module (missing symbol
> export on wilc_get_chipid)

I think I have a separate patch for this, one which folds 
wilc_get_chipid() entirely into wlan.c , and then follow up which uses 
is_wilc1000() / is_wilc3000() all over the place to discern the two MACs 
based on cached chip ID . That should work, I'll test it and submit it 
later today I hope.

> [...]
> 
>> -	/* select VMM table 0 */
>> -	if (val & SEL_VMM_TBL0)
>> -		reg |= BIT(5);
>> -	/* select VMM table 1 */
>> -	if (val & SEL_VMM_TBL1)
>> -		reg |= BIT(6);
>> -	/* enable VMM */
>> -	if (val & EN_VMM)
>> -		reg |= BIT(7);
>> +	if (wilc->chip == WILC_1000) {
> 
> wilc1000 should likely remain the default/fallback ?

I am now validating whether the hardware is either wilc1000 or wilc3000 
up front based on the chip ID early in init, so no other option can 
occur here, so there is no need for fallback, it is either wilc1000 or 
wilc3000 now (*). I think keeping them ordered alphanumerically is the 
nicer option.

> [...]
> 
>> @@ -1232,10 +1234,7 @@ static int wilc_validate_chipid(struct wilc *wilc)
>>   		dev_err(&spi->dev, "Fail cmd read chip id...\n");
>>   		return ret;
>>   	}
>> -	if (!is_wilc1000(chipid)) {
>> -		dev_err(&spi->dev, "Unknown chip id 0x%x\n", chipid);
>> -		return -ENODEV;
>> -	}
>> +
> 
> Instead of dropping any filtering (and then making the function name become
> irrelevant), why not ensuring that it is at least either a wilc1000 or a wilc3000 ?

Right, done.

[...]

>> +void chip_wakeup(struct wilc *wilc)
>> +{
>> +	if (wilc->chip == WILC_1000)
>> +		chip_wakeup_wilc1000(wilc);
>> +	else
>> +		chip_wakeup_wilc3000(wilc);
>> +}
>>   EXPORT_SYMBOL_GPL(chip_wakeup);
> 
> This new support makes a few places in wlan.c, netdev.c and in bus files
> (sdio.c, spi.c) install (sometimes big) branches on the device type (chip init,
> sleep, wakeup, read interrupt, clear interrupt, txq handling, etc), because the
> registers are different, the masks are different, the number of involved
> registers may not be the same, wilc3000 may need more operations to perform the
> same thing... I feel like it will make it harder in the long run to maintain the
> driver, especially if some new variants are added later.

I agree the code is ugly. Looking at the roadmap, it seems the next 
thing is WILCS02 which has its own driver, and for the WILC1000/3000 
inherited from atmel this seems to be the end of the road.

> Those branches tend to
> show that some operations in those files are too specific to the targeted
> device. I was examining the possibility to start creating device-type specific
> files (wilc1000.c, wilc3000.c) and move those operations as "device-specific"
> ops. Then wlan/netdev would call those chip-specific ops, which in turn may call
> the hif_func ops. It may need some rework in the bus files to fit this new
> hierarchy, but it may allow to keep netdev and wlan unaware of the device type,
> and since wilc3000 has bluetooth, it may also make it easier to introduce the
> corresponding support later. What do you think about it ? Ajay, any opinion on
> this ?

I did something like that for KSZ8851, that had bus-specific ops. I 
vaguely recall there was feedback that the function pointer indirection 
had non-trivial overhead due to spectre mitigations, and in case of the 
handle_txq() here, the chip specific ops would be called in a while() {} 
loop.

I can imagine some of the long functions like wilc_sdio_clear_int_ext or 
the handle_txq could be split up a bit, but likely only by factoring out 
some of the code into static functions. But looking at this closer, both 
pieces which are wilc1000/3000 specific in those functions manipulate 
with variables which would have to be passed in into that factored out 
code as function arguments, so I am not sure if this would improve 
readability by much either.

[...]
Krzysztof Kozlowski Aug. 23, 2024, 6:10 a.m. UTC | #7
On 23/08/2024 03:38, Marek Vasut wrote:
> On 8/22/24 10:07 AM, Krzysztof Kozlowski wrote:
> 
> Hi,
> 
>>> diff --git a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
>>> index 2460ccc082371..1bf3496c21e64 100644
>>> --- a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
>>> +++ b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
>>> @@ -16,7 +16,9 @@ description:
>>>   
>>>   properties:
>>>     compatible:
>>> -    const: microchip,wilc1000
>>> +    enum:
>>> +      - microchip,wilc1000
>>> +      - microchip,wilc3000
>>
>> Your driver change suggests device type is fully auto-detectable
> 
> It seems that way, yes.
> 
>> , thus
>> they are compatible.
> 
> I _think_ the hardware is internally somewhat different, the WILC1000 is 
> WiFi-only device and the WILC3000 has some extra Bluetooth part (which 
> is currently not supported).
> 
> Maybe a fallback compatible string would be better here ?

Yes, that's what I meant by compatibility. 3000 followed by 1000.

Best regards,
Krzysztof
Ajay.Kathat@microchip.com Aug. 23, 2024, 5:37 p.m. UTC | #8
On 8/22/24 19:46, Marek Vasut wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the
> content is safe
> 
> On 8/22/24 2:10 PM, Alexis Lothoré wrote:
>> Hello Marek,
> 
> Hi,
> 
>> I was coincidentally working on adding wilc3000 support upstream too.
> 
> I hope you weren't too far along with that and I didn't waste too much
> of your time/effort here.
> 
>> My work is
>> also based on downstream tree, so my comments will likely reflect the reworks I
>> was doing or intended to do.
>> For the record, I have some wilc1000 and wilc3000 modules, in both  sdio and
>> spi
>> setups.
> 
> Nice, I only have this WILC3000 SDIO device .
> 
>> On 8/21/24 20:42, Marek Vasut wrote:
>>> From: Ajay Singh <ajay.kathat@microchip.com>
>>
>> [...]
>>
>>>      if (!resume) {
>>> -            ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid);
>>> -            if (ret) {
>>> -                    dev_err(&func->dev, "Fail cmd read chip id...\n");
>>> +            chipid = wilc_get_chipid(wilc, true);
>>> +            if (is_wilc3000(chipid)) {
>>> +                    wilc->chip = WILC_3000;
>>> +            } else if (is_wilc1000(chipid)) {
>>> +                    wilc->chip = WILC_1000;
>>> +            } else {
>>> +                    dev_err(&func->dev, "Unsupported chipid: %x\n", chipid);
>>>                      return ret;
>>>              }
>>
>> I wonder if this additional enum (enum wilc_chip_type)  is really useful. We
>> already store the raw chipid, which just needs to be masked to know about the
>> device type. We should likely store one or the other but not both, otherwise we
>> may just risk to create desync without really saving useful info.
>>
>> Also, this change makes wilc1000-sdio failing to build as module (missing
>> symbol
>> export on wilc_get_chipid)
> 
> I think I have a separate patch for this, one which folds
> wilc_get_chipid() entirely into wlan.c , and then follow up which uses
> is_wilc1000() / is_wilc3000() all over the place to discern the two MACs
> based on cached chip ID . That should work, I'll test it and submit it
> later today I hope.
> 
>> [...]
>>
>>> -    /* select VMM table 0 */
>>> -    if (val & SEL_VMM_TBL0)
>>> -            reg |= BIT(5);
>>> -    /* select VMM table 1 */
>>> -    if (val & SEL_VMM_TBL1)
>>> -            reg |= BIT(6);
>>> -    /* enable VMM */
>>> -    if (val & EN_VMM)
>>> -            reg |= BIT(7);
>>> +    if (wilc->chip == WILC_1000) {
>>
>> wilc1000 should likely remain the default/fallback ?
> 
> I am now validating whether the hardware is either wilc1000 or wilc3000
> up front based on the chip ID early in init, so no other option can
> occur here, so there is no need for fallback, it is either wilc1000 or
> wilc3000 now (*). I think keeping them ordered alphanumerically is the
> nicer option.
> 
>> [...]
>>
>>> @@ -1232,10 +1234,7 @@ static int wilc_validate_chipid(struct wilc *wilc)
>>>              dev_err(&spi->dev, "Fail cmd read chip id...\n");
>>>              return ret;
>>>      }
>>> -    if (!is_wilc1000(chipid)) {
>>> -            dev_err(&spi->dev, "Unknown chip id 0x%x\n", chipid);
>>> -            return -ENODEV;
>>> -    }
>>> +
>>
>> Instead of dropping any filtering (and then making the function name become
>> irrelevant), why not ensuring that it is at least either a wilc1000 or a
>> wilc3000 ?
> 
> Right, done.
> 
> [...]
> 
>>> +void chip_wakeup(struct wilc *wilc)
>>> +{
>>> +    if (wilc->chip == WILC_1000)
>>> +            chip_wakeup_wilc1000(wilc);
>>> +    else
>>> +            chip_wakeup_wilc3000(wilc);
>>> +}
>>>   EXPORT_SYMBOL_GPL(chip_wakeup);
>>
>> This new support makes a few places in wlan.c, netdev.c and in bus files
>> (sdio.c, spi.c) install (sometimes big) branches on the device type (chip init,
>> sleep, wakeup, read interrupt, clear interrupt, txq handling, etc), because the
>> registers are different, the masks are different, the number of involved
>> registers may not be the same, wilc3000 may need more operations to perform the
>> same thing... I feel like it will make it harder in the long run to maintain
>> the
>> driver, especially if some new variants are added later.
> 
> I agree the code is ugly. Looking at the roadmap, it seems the next
> thing is WILCS02 which has its own driver, and for the WILC1000/3000
> inherited from atmel this seems to be the end of the road

yes, WILCS02 is the next-generation product of WILC family. It supports both
SDIO and SPI(mmc-over-spi) and the driver is same as  WILC1000/3000. The same
sdio driver will be used for mmc-over-spi interface. Similar to wilc3000, the
wilcs02 have different register sets and minor difference in firmware start
and txq_handling flow. The single driver will support all WILC variants.

> 
>> Those branches tend to
>> show that some operations in those files are too specific to the targeted
>> device. I was examining the possibility to start creating device-type specific
>> files (wilc1000.c, wilc3000.c) and move those operations as "device-specific"
>> ops. Then wlan/netdev would call those chip-specific ops, which in turn may
>> call
>> the hif_func ops. It may need some rework in the bus files to fit this new
>> hierarchy, but it may allow to keep netdev and wlan unaware of the device type,
>> and since wilc3000 has bluetooth, it may also make it easier to introduce the
>> corresponding support later. What do you think about it ? Ajay, any opinion on
>> this ?
> 
> I did something like that for KSZ8851, that had bus-specific ops. I
> vaguely recall there was feedback that the function pointer indirection
> had non-trivial overhead due to spectre mitigations, and in case of the
> handle_txq() here, the chip specific ops would be called in a while() {}
> loop.
> 
> I can imagine some of the long functions like wilc_sdio_clear_int_ext or
> the handle_txq could be split up a bit, but likely only by factoring out
> some of the code into static functions. But looking at this closer, both
> pieces which are wilc1000/3000 specific in those functions manipulate
> with variables which would have to be passed in into that factored out
> code as function arguments, so I am not sure if this would improve
> readability by much either.
> 

I also think adding wilc1000/wilc3000 specific may not improve much but some
of the large functions can be refactored if it improves the readability. For
most part, wilc1000 and wilc3000 has similar code but it mainly differs in
txq_handle handling, which may not be improved even after separating the code
to wilc1000 and wilc3000 specific files.
diff mbox series

Patch

diff --git a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
index 2460ccc082371..1bf3496c21e64 100644
--- a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
@@ -16,7 +16,9 @@  description:
 
 properties:
   compatible:
-    const: microchip,wilc1000
+    enum:
+      - microchip,wilc1000
+      - microchip,wilc3000
 
   reg: true