[PATCH v2 09/32] swim: Recalibrate when drive is probed

From: Finn Thain

Date: Sun Aug 16 2026 - 21:58:03 EST


Track zero recalibration can be slow and is normally done only once i.e.
during system POST or boot-up. Recalibrate once after the drive is probed
rather than every time the device is opened. Don't register the drive if
recalibration fails. Park the heads before ejecting.

Reviewed-by: Laurent Vivier <laurent@xxxxxxxxx>
Fixes: 8852ecd97488 ("m68k: mac - Add SWIM floppy support")
Signed-off-by: Finn Thain <fthain@xxxxxxxxxxxxxx>
---
Changed since v1:
- Refactor swim_add_floppy() slightly. Start spindle motor before
recalibration if a disk is loaded.
- Change return type of swim_add_floppy() to void.
- Park heads at track 40 because that's what MacOS does.
---
drivers/block/swim.c | 37 +++++++++++++++++--------------------
1 file changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/block/swim.c b/drivers/block/swim.c
index 6a49fc51f5d2..9abf93bc0980 100644
--- a/drivers/block/swim.c
+++ b/drivers/block/swim.c
@@ -412,6 +412,7 @@ static inline int swim_track00(struct swim __iomem *base)
if (swim_readbit(base, TRACK_ZERO))
return 0;

+ pr_err("swim: track zero recalibration failed\n");
return -1;
}

@@ -456,6 +457,7 @@ static int floppy_eject(struct floppy_state *fs)
struct swim __iomem *base = fs->swd->base;

swim_drive(base, fs->location);
+ swim_track(fs, 40);
swim_motor(base, OFF);
swim_eject(base);
swim_drive(base, NO_DRIVE);
@@ -596,13 +598,6 @@ static void setup_medium(struct floppy_state *fs)
struct floppy_struct *g;
fs->disk_in = 1;
fs->write_protected = swim_readbit(base, WRITE_PROT);
-
- if (swim_track00(base))
- printk(KERN_ERR
- "SWIM: cannot move floppy head to track 0\n");
-
- swim_track00(base);
-
fs->type = swim_readbit(base, TWOMEG_MEDIA) ?
HD_MEDIA : DD_MEDIA;
fs->head_number = swim_readbit(base, SINGLE_SIDED) ? 1 : 2;
@@ -610,7 +605,6 @@ static void setup_medium(struct floppy_state *fs)
fs->total_secs = g->size;
fs->secpercyl = g->head * g->sect;
fs->secpertrack = g->sect;
- fs->track = 0;
} else {
fs->disk_in = 0;
}
@@ -759,24 +753,33 @@ static const struct block_device_operations floppy_fops = {
.check_events = floppy_check_events,
};

-static int swim_add_floppy(struct swim_priv *swd, enum drive_location location)
+static void swim_add_floppy(struct swim_priv *swd, enum drive_location location)
{
struct floppy_state *fs = &swd->unit[swd->floppy_count];
struct swim __iomem *base = swd->base;

- fs->location = location;
+ swim_drive(base, location);
+ if (!swim_readbit(base, DRIVE_PRESENT) ||
+ swim_readbit(base, ONEMEG_DRIVE))
+ goto out;
+ if (swim_readbit(base, DISK_IN))
+ swim_motor(base, ON);
+ if (swim_track00(base))
+ goto out;

- swim_motor(base, OFF);
+ fs->location = location;

fs->type = HD_MEDIA;
fs->head_number = 2;

fs->ref_count = 0;
fs->ejected = 1;
+ fs->track = 0;

swd->floppy_count++;

- return 0;
+out:
+ swim_motor(base, OFF);
}

static const struct blk_mq_ops swim_mq_ops = {
@@ -825,14 +828,8 @@ static int swim_floppy_init(struct platform_device *pdev)

/* scan floppy drives */

- swim_drive(base, INTERNAL_DRIVE);
- if (swim_readbit(base, DRIVE_PRESENT) &&
- !swim_readbit(base, ONEMEG_DRIVE))
- swim_add_floppy(swd, INTERNAL_DRIVE);
- swim_drive(base, EXTERNAL_DRIVE);
- if (swim_readbit(base, DRIVE_PRESENT) &&
- !swim_readbit(base, ONEMEG_DRIVE))
- swim_add_floppy(swd, EXTERNAL_DRIVE);
+ swim_add_floppy(swd, INTERNAL_DRIVE);
+ swim_add_floppy(swd, EXTERNAL_DRIVE);
swim_drive(base, NO_DRIVE);

/* register floppy drives */
--
2.52.0