Module Name: src Committed By: rin Date: Mon Oct 11 02:30:01 UTC 2021
Modified Files: src/sys/arch/hpcsh/dev/hd64461: hd64461pcmcia.c Log Message: Fix workaround for SH-3 PCMCIA bug in accordance with description found in TECH I vol. 14 (CQ Publishing, Tokyo, 2002, in Japanese), as well as experiment on real hardware: Byte-access to area 6 becomes word-access (both CE1# and CE2# are wrongly asserted), if preceding access is word-wise. Inserting a dummy byte-access works around the problem. Area 5 is not affected. Therefore, (1) Insert a dummy byte-read before all byte-wise operations. (2) Restrict the workaround to area 6 (channel 0), and rename fixup_sh3_pcmcia_area() to fixup_sh3_pcmcia_area6() for clarity. Also, we used to use 0xba000000 (== HD64461_PCC0_IOBASE) as target for the dummy read. However, this can modify device states, which breaks ep(4) at least. Thus, (3) Use HD64461_PCC0_MEMBASE as target for the dummy read. This is assigned to attribute memory space, and byte-read should be harmless. To generate a diff of this commit: cvs rdiff -u -r1.54 -r1.55 src/sys/arch/hpcsh/dev/hd64461/hd64461pcmcia.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/hpcsh/dev/hd64461/hd64461pcmcia.c diff -u src/sys/arch/hpcsh/dev/hd64461/hd64461pcmcia.c:1.54 src/sys/arch/hpcsh/dev/hd64461/hd64461pcmcia.c:1.55 --- src/sys/arch/hpcsh/dev/hd64461/hd64461pcmcia.c:1.54 Sat Aug 7 16:18:54 2021 +++ src/sys/arch/hpcsh/dev/hd64461/hd64461pcmcia.c Mon Oct 11 02:30:00 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: hd64461pcmcia.c,v 1.54 2021/08/07 16:18:54 thorpej Exp $ */ +/* $NetBSD: hd64461pcmcia.c,v 1.55 2021/10/11 02:30:00 rin Exp $ */ /*- * Copyright (c) 2001, 2002, 2004 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: hd64461pcmcia.c,v 1.54 2021/08/07 16:18:54 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hd64461pcmcia.c,v 1.55 2021/10/11 02:30:00 rin Exp $"); #include "opt_hd64461pcmcia.h" @@ -223,17 +223,37 @@ STATIC void hd64461_set_bus_width(enum c #ifdef HD64461PCMCIA_DEBUG STATIC void hd64461pcmcia_info(struct hd64461pcmcia_softc *); #endif -/* fix SH3 Area[56] bug */ -STATIC void fixup_sh3_pcmcia_area(bus_space_tag_t); + +/* + * Workaround for SH-3 PCMCIA bug on area 6: + * + * According to TECH I vol. 14 (CQ Publishing, Tokyo, 2002) p. 184, + * byte-access to area 6 becomes word-access if preceding access is + * word-wise. Inserting a dummy byte-access works around the problem. + * Area 5 is not affected by this bug. + * + * Therefore, we insert a dummy byte-wise read to HD64461_PCC0_MEMBASE + * before any byte-access to area 6 (channel 0). + * + * Note that we used to use HD64461_PCC0_IOBASE for this purpose. But, + * read access to that register can modify device states, which breaks + * ep(4) at least. On the other hand, since HD64461_PCC0_MEMBASE is + * assigned to attribute memory, read access should be harmless. + */ +STATIC void fixup_sh3_pcmcia_area6(bus_space_tag_t); #define _BUS_SPACE_ACCESS_HOOK() \ -do { \ - uint8_t dummy __attribute__((__unused__)) = \ - *(volatile uint8_t *)0xba000000; \ -} while (/*CONSTCOND*/0) + do { \ + uint8_t dummy __unused = \ + *(volatile uint8_t *)HD64461_PCC0_MEMBASE; \ + } while (0) +_BUS_SPACE_READ(_sh3_pcmcia_bug, 1, 8) +_BUS_SPACE_READ_MULTI(_sh3_pcmcia_bug, 1, 8) +_BUS_SPACE_READ_REGION(_sh3_pcmcia_bug, 1, 8) _BUS_SPACE_WRITE(_sh3_pcmcia_bug, 1, 8) _BUS_SPACE_WRITE_MULTI(_sh3_pcmcia_bug, 1, 8) _BUS_SPACE_WRITE_REGION(_sh3_pcmcia_bug, 1, 8) _BUS_SPACE_SET_MULTI(_sh3_pcmcia_bug, 1, 8) +_BUS_SPACE_COPY_REGION(_sh3_pcmcia_bug, 1, 8) #undef _BUS_SPACE_ACCESS_HOOK #define DELAY_MS(x) delay((x) * 1000) @@ -386,7 +406,8 @@ hd64461pcmcia_attach_channel(struct hd64 bus_space_alloc(ch->ch_memt, 0, 0x00ffffff, 0x01000000, 0x01000000, 0x01000000, 0, &ch->ch_membase_addr, &ch->ch_memh); - fixup_sh3_pcmcia_area(ch->ch_memt); + if (channel == CHANNEL_0) + fixup_sh3_pcmcia_area6(ch->ch_memt); /* Common memory space extent */ ch->ch_memsize = 0x01000000; @@ -394,7 +415,8 @@ hd64461pcmcia_attach_channel(struct hd64 ch->ch_cmemt[i] = bus_space_create(0, "PCMCIA common memory", membase + 0x01000000, ch->ch_memsize); - fixup_sh3_pcmcia_area(ch->ch_cmemt[i]); + if (channel == CHANNEL_0) + fixup_sh3_pcmcia_area6(ch->ch_cmemt[i]); } /* I/O port extent and interrupt staff */ @@ -406,7 +428,7 @@ hd64461pcmcia_attach_channel(struct hd64 ch->ch_iot = bus_space_create(0, "PCMCIA I/O port", HD64461_PCC0_IOBASE, ch->ch_iosize); - fixup_sh3_pcmcia_area(ch->ch_iot); + fixup_sh3_pcmcia_area6(ch->ch_iot); hd6446x_intr_establish(HD64461_INTC_PCC0, IST_LEVEL, IPL_TTY, hd64461pcmcia_channel0_intr, ch); @@ -1081,14 +1103,18 @@ hd64461_set_bus_width(enum controller_ch } STATIC void -fixup_sh3_pcmcia_area(bus_space_tag_t t) +fixup_sh3_pcmcia_area6(bus_space_tag_t t) { struct hpcsh_bus_space *hbs = (void *)t; + hbs->hbs_r_1 = _sh3_pcmcia_bug_read_1; + hbs->hbs_rm_1 = _sh3_pcmcia_bug_read_multi_1; + hbs->hbs_rr_1 = _sh3_pcmcia_bug_read_region_1; hbs->hbs_w_1 = _sh3_pcmcia_bug_write_1; hbs->hbs_wm_1 = _sh3_pcmcia_bug_write_multi_1; hbs->hbs_wr_1 = _sh3_pcmcia_bug_write_region_1; hbs->hbs_sm_1 = _sh3_pcmcia_bug_set_multi_1; + hbs->hbs_c_1 = _sh3_pcmcia_bug_copy_region_1; } #ifdef HD64461PCMCIA_DEBUG