lkml.org 
[lkml]   [2019]   [Apr]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH v2 3/4] MIPS: SGI-IP27: fix readb/writeb addressing
On 09/04/2019 17:46:07+0200, Thomas Bogendoerfer wrote:
> Our chosen byte swapping, which is what firmware already uses, is to
> do readl/writel by normal lw/sw intructions (data invariance). This
> also means we need to mangle addresses for u8 and u16 accesses. The
> mangling for 16bit has been done aready, but 8bit one was missing.
> Correcting this causes different addresses for accesses to the
> SuperIO and local bus of the IOC3 chip. This is fixed by changing
> byte order in ioc3 and m48rtc_rtc structs.
>
> Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>

Considering this is probably the only platform to have that RTC and that
is probably not worth having a better fix for a platform this old:

Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

> ---
> arch/mips/include/asm/mach-ip27/mangle-port.h | 2 +-
> arch/mips/include/asm/sn/ioc3.h | 198 +++++++++++++-------------
> arch/mips/sgi-ip27/ip27-console.c | 5 +-
> drivers/rtc/rtc-m48t35.c | 11 ++
> drivers/tty/serial/8250/8250_ioc3.c | 4 +-
> 5 files changed, 114 insertions(+), 106 deletions(-)
>
> diff --git a/arch/mips/include/asm/mach-ip27/mangle-port.h b/arch/mips/include/asm/mach-ip27/mangle-port.h
> index f6e4912ea062..7771ae0f3971 100644
> --- a/arch/mips/include/asm/mach-ip27/mangle-port.h
> +++ b/arch/mips/include/asm/mach-ip27/mangle-port.h
> @@ -8,7 +8,7 @@
> #ifndef __ASM_MACH_IP27_MANGLE_PORT_H
> #define __ASM_MACH_IP27_MANGLE_PORT_H
>
> -#define __swizzle_addr_b(port) (port)
> +#define __swizzle_addr_b(port) ((port) ^ 3)
> #define __swizzle_addr_w(port) ((port) ^ 2)
> #define __swizzle_addr_l(port) (port)
> #define __swizzle_addr_q(port) (port)
> diff --git a/arch/mips/include/asm/sn/ioc3.h b/arch/mips/include/asm/sn/ioc3.h
> index 69069f420930..059885d736de 100644
> --- a/arch/mips/include/asm/sn/ioc3.h
> +++ b/arch/mips/include/asm/sn/ioc3.h
> @@ -10,35 +10,35 @@
>
> /* serial port register map */
> struct ioc3_serialregs {
> - uint32_t sscr;
> - uint32_t stpir;
> - uint32_t stcir;
> - uint32_t srpir;
> - uint32_t srcir;
> - uint32_t srtr;
> - uint32_t shadow;
> + u32 sscr;
> + u32 stpir;
> + u32 stcir;
> + u32 srpir;
> + u32 srcir;
> + u32 srtr;
> + u32 shadow;
> };
>
> /* SUPERIO uart register map */
> struct ioc3_uartregs {
> + u8 iu_lcr;
> union {
> - char rbr; /* read only, DLAB == 0 */
> - char thr; /* write only, DLAB == 0 */
> - char dll; /* DLAB == 1 */
> - } u1;
> + u8 iir; /* read only */
> + u8 fcr; /* write only */
> + };
> union {
> - char ier; /* DLAB == 0 */
> - char dlm; /* DLAB == 1 */
> - } u2;
> + u8 ier; /* DLAB == 0 */
> + u8 dlm; /* DLAB == 1 */
> + };
> union {
> - char iir; /* read only */
> - char fcr; /* write only */
> - } u3;
> - char iu_lcr;
> - char iu_mcr;
> - char iu_lsr;
> - char iu_msr;
> - char iu_scr;
> + u8 rbr; /* read only, DLAB == 0 */
> + u8 thr; /* write only, DLAB == 0 */
> + u8 dll; /* DLAB == 1 */
> + } u1;
> + u8 iu_scr;
> + u8 iu_msr;
> + u8 iu_lsr;
> + u8 iu_mcr;
> };
>
> #define iu_rbr u1.rbr
> @@ -50,122 +50,122 @@ struct ioc3_uartregs {
> #define iu_fcr u3.fcr
>
> struct ioc3_sioregs {
> - char fill[0x141]; /* starts at 0x141 */
> + u8 fill[0x141]; /* starts at 0x141 */
>
> - char uartc;
> - char kbdcg;
> + u8 kbdcg;
> + u8 uartc;
>
> - char fill0[0x150 - 0x142 - 1];
> + u8 fill0[0x151 - 0x142 - 1];
>
> - char pp_data;
> - char pp_dsr;
> - char pp_dcr;
> + u8 pp_dcr;
> + u8 pp_dsr;
> + u8 pp_data;
>
> - char fill1[0x158 - 0x152 - 1];
> + u8 fill1[0x159 - 0x153 - 1];
>
> - char pp_fifa;
> - char pp_cfgb;
> - char pp_ecr;
> + u8 pp_ecr;
> + u8 pp_cfgb;
> + u8 pp_fifa;
>
> - char fill2[0x168 - 0x15a - 1];
> + u8 fill2[0x16a - 0x15b - 1];
>
> - char rtcad;
> - char rtcdat;
> + u8 rtcdat;
> + u8 rtcad;
>
> - char fill3[0x170 - 0x169 - 1];
> + u8 fill3[0x170 - 0x16b - 1];
>
> struct ioc3_uartregs uartb; /* 0x20170 */
> struct ioc3_uartregs uarta; /* 0x20178 */
> };
>
> struct ioc3_ethregs {
> - uint32_t emcr; /* 0x000f0 */
> - uint32_t eisr; /* 0x000f4 */
> - uint32_t eier; /* 0x000f8 */
> - uint32_t ercsr; /* 0x000fc */
> - uint32_t erbr_h; /* 0x00100 */
> - uint32_t erbr_l; /* 0x00104 */
> - uint32_t erbar; /* 0x00108 */
> - uint32_t ercir; /* 0x0010c */
> - uint32_t erpir; /* 0x00110 */
> - uint32_t ertr; /* 0x00114 */
> - uint32_t etcsr; /* 0x00118 */
> - uint32_t ersr; /* 0x0011c */
> - uint32_t etcdc; /* 0x00120 */
> - uint32_t ebir; /* 0x00124 */
> - uint32_t etbr_h; /* 0x00128 */
> - uint32_t etbr_l; /* 0x0012c */
> - uint32_t etcir; /* 0x00130 */
> - uint32_t etpir; /* 0x00134 */
> - uint32_t emar_h; /* 0x00138 */
> - uint32_t emar_l; /* 0x0013c */
> - uint32_t ehar_h; /* 0x00140 */
> - uint32_t ehar_l; /* 0x00144 */
> - uint32_t micr; /* 0x00148 */
> - uint32_t midr_r; /* 0x0014c */
> - uint32_t midr_w; /* 0x00150 */
> + u32 emcr; /* 0x000f0 */
> + u32 eisr; /* 0x000f4 */
> + u32 eier; /* 0x000f8 */
> + u32 ercsr; /* 0x000fc */
> + u32 erbr_h; /* 0x00100 */
> + u32 erbr_l; /* 0x00104 */
> + u32 erbar; /* 0x00108 */
> + u32 ercir; /* 0x0010c */
> + u32 erpir; /* 0x00110 */
> + u32 ertr; /* 0x00114 */
> + u32 etcsr; /* 0x00118 */
> + u32 ersr; /* 0x0011c */
> + u32 etcdc; /* 0x00120 */
> + u32 ebir; /* 0x00124 */
> + u32 etbr_h; /* 0x00128 */
> + u32 etbr_l; /* 0x0012c */
> + u32 etcir; /* 0x00130 */
> + u32 etpir; /* 0x00134 */
> + u32 emar_h; /* 0x00138 */
> + u32 emar_l; /* 0x0013c */
> + u32 ehar_h; /* 0x00140 */
> + u32 ehar_l; /* 0x00144 */
> + u32 micr; /* 0x00148 */
> + u32 midr_r; /* 0x0014c */
> + u32 midr_w; /* 0x00150 */
> };
>
> struct ioc3_serioregs {
> - uint32_t km_csr; /* 0x0009c */
> - uint32_t k_rd; /* 0x000a0 */
> - uint32_t m_rd; /* 0x000a4 */
> - uint32_t k_wd; /* 0x000a8 */
> - uint32_t m_wd; /* 0x000ac */
> + u32 km_csr; /* 0x0009c */
> + u32 k_rd; /* 0x000a0 */
> + u32 m_rd; /* 0x000a4 */
> + u32 k_wd; /* 0x000a8 */
> + u32 m_wd; /* 0x000ac */
> };
>
> /* Register layout of IOC3 in configuration space. */
> struct ioc3 {
> /* PCI Config Space registers */
> - uint32_t pci_id; /* 0x00000 */
> - uint32_t pci_scr; /* 0x00004 */
> - uint32_t pci_rev; /* 0x00008 */
> - uint32_t pci_lat; /* 0x0000c */
> - uint32_t pci_addr; /* 0x00010 */
> - uint32_t pci_err_addr_l; /* 0x00014 */
> - uint32_t pci_err_addr_h; /* 0x00018 */
> -
> - uint32_t sio_ir; /* 0x0001c */
> - uint32_t sio_ies; /* 0x00020 */
> - uint32_t sio_iec; /* 0x00024 */
> - uint32_t sio_cr; /* 0x00028 */
> - uint32_t int_out; /* 0x0002c */
> - uint32_t mcr; /* 0x00030 */
> + u32 pci_id; /* 0x00000 */
> + u32 pci_scr; /* 0x00004 */
> + u32 pci_rev; /* 0x00008 */
> + u32 pci_lat; /* 0x0000c */
> + u32 pci_addr; /* 0x00010 */
> + u32 pci_err_addr_l; /* 0x00014 */
> + u32 pci_err_addr_h; /* 0x00018 */
> +
> + u32 sio_ir; /* 0x0001c */
> + u32 sio_ies; /* 0x00020 */
> + u32 sio_iec; /* 0x00024 */
> + u32 sio_cr; /* 0x00028 */
> + u32 int_out; /* 0x0002c */
> + u32 mcr; /* 0x00030 */
>
> /* General Purpose I/O registers */
> - uint32_t gpcr_s; /* 0x00034 */
> - uint32_t gpcr_c; /* 0x00038 */
> - uint32_t gpdr; /* 0x0003c */
> - uint32_t gppr[16]; /* 0x00040 */
> + u32 gpcr_s; /* 0x00034 */
> + u32 gpcr_c; /* 0x00038 */
> + u32 gpdr; /* 0x0003c */
> + u32 gppr[16]; /* 0x00040 */
>
> /* Parallel Port Registers */
> - uint32_t ppbr_h_a; /* 0x00080 */
> - uint32_t ppbr_l_a; /* 0x00084 */
> - uint32_t ppcr_a; /* 0x00088 */
> - uint32_t ppcr; /* 0x0008c */
> - uint32_t ppbr_h_b; /* 0x00090 */
> - uint32_t ppbr_l_b; /* 0x00094 */
> - uint32_t ppcr_b; /* 0x00098 */
> + u32 ppbr_h_a; /* 0x00080 */
> + u32 ppbr_l_a; /* 0x00084 */
> + u32 ppcr_a; /* 0x00088 */
> + u32 ppcr; /* 0x0008c */
> + u32 ppbr_h_b; /* 0x00090 */
> + u32 ppbr_l_b; /* 0x00094 */
> + u32 ppcr_b; /* 0x00098 */
>
> /* Keyboard and Mouse Registers */
> struct ioc3_serioregs serio;
>
> /* Serial Port Registers */
> - uint32_t sbbr_h; /* 0x000b0 */
> - uint32_t sbbr_l; /* 0x000b4 */
> + u32 sbbr_h; /* 0x000b0 */
> + u32 sbbr_l; /* 0x000b4 */
> struct ioc3_serialregs port_a;
> struct ioc3_serialregs port_b;
>
> /* Ethernet Registers */
> struct ioc3_ethregs eth;
> - uint32_t pad1[(0x20000 - 0x00154) / 4];
> + u32 pad1[(0x20000 - 0x00154) / 4];
>
> /* SuperIO Registers XXX */
> struct ioc3_sioregs sregs; /* 0x20000 */
> - uint32_t pad2[(0x40000 - 0x20180) / 4];
> + u32 pad2[(0x40000 - 0x20180) / 4];
>
> /* SSRAM Diagnostic Access */
> - uint32_t ssram[(0x80000 - 0x40000) / 4];
> + u32 ssram[(0x80000 - 0x40000) / 4];
>
> /* Bytebus device offsets
> 0x80000 - Access to the generic devices selected with DEV0
> @@ -598,8 +598,4 @@ struct ioc3_etxd {
>
> #define MIDR_DATA_MASK 0x0000ffff
>
> -#if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP30)
> -extern int bridge_alloc_irq(struct pci_dev *dev);
> -#endif
> -
> #endif /* MIPS_SN_IOC3_H */
> diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c
> index 6bdb48d41276..5886bee89d06 100644
> --- a/arch/mips/sgi-ip27/ip27-console.c
> +++ b/arch/mips/sgi-ip27/ip27-console.c
> @@ -35,6 +35,7 @@ void prom_putchar(char c)
> {
> struct ioc3_uartregs *uart = console_uart();
>
> - while ((uart->iu_lsr & 0x20) == 0);
> - uart->iu_thr = c;
> + while ((readb(&uart->iu_lsr) & 0x20) == 0)
> + ;
> + writeb(c, &uart->iu_thr);
> }
> diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c
> index 0cf6507de3c7..05f0d91366af 100644
> --- a/drivers/rtc/rtc-m48t35.c
> +++ b/drivers/rtc/rtc-m48t35.c
> @@ -24,6 +24,16 @@
>
> struct m48t35_rtc {
> u8 pad[0x7ff8]; /* starts at 0x7ff8 */
> +#ifdef CONFIG_SGI_IP27
> + u8 hour;
> + u8 min;
> + u8 sec;
> + u8 control;
> + u8 year;
> + u8 month;
> + u8 date;
> + u8 day;
> +#else
> u8 control;
> u8 sec;
> u8 min;
> @@ -32,6 +42,7 @@ struct m48t35_rtc {
> u8 date;
> u8 month;
> u8 year;
> +#endif
> };
>
> #define M48T35_RTC_SET 0x80
> diff --git a/drivers/tty/serial/8250/8250_ioc3.c b/drivers/tty/serial/8250/8250_ioc3.c
> index 2be6ed2967e0..4c405f1b9c67 100644
> --- a/drivers/tty/serial/8250/8250_ioc3.c
> +++ b/drivers/tty/serial/8250/8250_ioc3.c
> @@ -23,12 +23,12 @@ struct ioc3_8250_data {
>
> static unsigned int ioc3_serial_in(struct uart_port *p, int offset)
> {
> - return readb(p->membase + offset);
> + return readb(p->membase + (offset ^ 3));
> }
>
> static void ioc3_serial_out(struct uart_port *p, int offset, int value)
> {
> - writeb(value, p->membase + offset);
> + writeb(value, p->membase + (offset ^ 3));
> }
>
> static int serial8250_ioc3_probe(struct platform_device *pdev)
> --
> 2.13.7
>

--
Alexandre Belloni, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

\
 
 \ /
  Last update: 2019-04-11 23:18    [W:0.099 / U:0.432 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site