Re: [PATCH 05/31] swim: Perform ISM/IWM mode switching according to specs

Laurent Vivier <[email protected]> Mon, 20 Jul 2026 20:20:53 +0200
Newsgroups org.kernel.vger.linux-m68k,org.kernel.vger.linux-block,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Le 16/07/2026 =C3=A0 12:02, Finn Thain a =C3=A9crit=C2=A0:
> The SWIM spec says, "MOTOREN must be low to switch modes" and "after
> switching from ISM to IWM, the very first command must be a clear L7".
>=20
> The ISM spec says, MOTOREN "must not be cleared until after the Action
> bit is cleared". Perform those operations in the correct sequence.
>=20
> When switching to ISM mode, the Mode register has to be selected with a
> particular sequence of bit flips. Set q7 low then q6 low then mtrOff.
>=20
> Fixes: 8852ecd97488 ("m68k: mac - Add SWIM floppy support")
> Signed-off-by: Finn Thain <[email protected]>
> ---
>   drivers/block/swim.c | 10 +++++++---
>   1 file changed, 7 insertions(+), 3 deletions(-)
>=20
> diff --git a/drivers/block/swim.c b/drivers/block/swim.c
> index f9c59282b81f..7499ff250ca7 100644
> --- a/drivers/block/swim.c
> +++ b/drivers/block/swim.c
> @@ -149,6 +149,7 @@ struct iwm {
>   #define ACTION		0x08
>   #define WRITE_MODE	0x10
>   #define HEDSEL		0x20
> +#define ISM_SELECT	0x40
>   #define MOTON		0x80
>  =20
>   /*--------------------------------------------------------------------=
=2D-------*/
> @@ -223,18 +224,21 @@ extern int swim_read_sector_data(struct swim __iom=
em *base,
>   static DEFINE_MUTEX(swim_mutex);
>   static inline void set_swim_mode(struct swim __iomem *base, int enable=
)
>   {
> -	struct iwm __iomem *iwm_base;
> +	struct iwm __iomem *iwm_base =3D (struct iwm __iomem *)base;
>   	unsigned long flags;
>  =20
>   	if (!enable) {
> -		swim_write(base, mode0, 0xf8);
> +		swim_write(base, mode0, ACTION);
> +		swim_write(base, mode0, ENBL1 | ENBL2 | MOTON);
> +		swim_write(base, mode0, ISM_SELECT);
> +		iwm_read(iwm_base, q7L);
>   		return;
>   	}
>  =20
> -	iwm_base =3D (struct iwm __iomem *)base;
>   	local_irq_save(flags);
>  =20
>   	iwm_read(iwm_base, q7L);
> +	iwm_read(iwm_base, q6L);
>   	iwm_read(iwm_base, mtrOff);
>   	iwm_read(iwm_base, q6H);
>  =20

Reviewed-by: Laurent Vivier <[email protected]>