From nobody Mon Oct 6 08:31:25 2025 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7E8BA28980A for ; Wed, 23 Jul 2025 11:58:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753271914; cv=none; b=Mt5626PNULBLt0J4EiOoKXBlqaTvr6Pr9bnIxTTaHzqMvDgQeAiOqBa2jSMgR/JfVGru+VNzYp//d4KpQyhFjo198vcguJsG5SirY/WjG5FlVeajF1KQ4no/FgcJpZgRslae4olGze7JSmkKgUiKa8/QVLYjeaThOLe0yfZ0GEQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753271914; c=relaxed/simple; bh=Nn6cAiRFvh9Sgl8x3J9o3XyA7o/CcHt0eytQPD9B5h4=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=NFXyb37hi3SOleXH2JGMh9adX6nJp3pa8jkhF/60h1RmKRCL9t90G+8HczM2NVVQK1Rb152hFAwNZcIImgwz2p2CE+BKVeu/tT/yfTM+KbprraJfJDmmzMCHhpmBBdFtJvBHwhpgU6JQbvB3sJsnQ+4PA06TkAN52vFHkrBFHSY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alpha.franken.de; spf=fail smtp.mailfrom=alpha.franken.de; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alpha.franken.de Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=alpha.franken.de Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 783152128A; Wed, 23 Jul 2025 11:58:27 +0000 (UTC) Authentication-Results: smtp-out1.suse.de; none Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 61B8F13ABE; Wed, 23 Jul 2025 11:58:27 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id gkW4F2POgGjGBAAAD6G6ig (envelope-from ); Wed, 23 Jul 2025 11:58:27 +0000 From: Thomas Bogendoerfer To: Greg Kroah-Hartman , Jiri Slaby , linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org Subject: [PATCH] tty: serial: ip22zilog: Use platform device for probing Date: Wed, 23 Jul 2025 13:58:23 +0200 Message-ID: <20250723115823.76341-1-tsbogend@alpha.franken.de> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Level: X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; TO_MATCH_ENVRCPT_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; MIME_TRACE(0.00)[0:+]; TO_DN_SOME(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; ARC_NA(0.00)[]; FUZZY_RATELIMITED(0.00)[rspamd.com]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; RCPT_COUNT_FIVE(0.00)[5]; RCVD_TLS_ALL(0.00)[] X-Spam-Flag: NO X-Spam-Score: -2.80 Content-Type: text/plain; charset="utf-8" After commit 84a9582fd203 ("serial: core: Start managing serial controllers to enable runtime PM") serial drivers need to provide a device in struct uart_port.dev otherwise an oops happens. To fix this issue for ip22zilog driver switch driver to a platform driver and setup the serial device in sgi-ip22 code. Signed-off-by: Thomas Bogendoerfer --- arch/mips/sgi-ip22/ip22-platform.c | 39 ++++ drivers/tty/serial/ip22zilog.c | 360 ++++++++++++----------------- 2 files changed, 186 insertions(+), 213 deletions(-) diff --git a/arch/mips/sgi-ip22/ip22-platform.c b/arch/mips/sgi-ip22/ip22-p= latform.c index 0b2002e02a47..592b7f4085d9 100644 --- a/arch/mips/sgi-ip22/ip22-platform.c +++ b/arch/mips/sgi-ip22/ip22-platform.c @@ -221,3 +221,42 @@ static int __init sgi_ds1286_devinit(void) } =20 device_initcall(sgi_ds1286_devinit); + +#define SGI_ZILOG_BASE (HPC3_CHIP0_BASE + \ + offsetof(struct hpc3_regs, pbus_extregs[6]) + \ + offsetof(struct sgioc_regs, uart)) + +static struct resource sgi_zilog_resources[] =3D { + { + .start =3D SGI_ZILOG_BASE, + .end =3D SGI_ZILOG_BASE + 15, + .flags =3D IORESOURCE_MEM + }, + { + .start =3D SGI_SERIAL_IRQ, + .end =3D SGI_SERIAL_IRQ, + .flags =3D IORESOURCE_IRQ + } +}; + +static struct platform_device zilog_device =3D { + .name =3D "ip22zilog", + .id =3D 0, + .num_resources =3D ARRAY_SIZE(sgi_zilog_resources), + .resource =3D sgi_zilog_resources, +}; + + +static int __init sgi_zilog_devinit(void) +{ + struct resource res; + + memset(&res, 0, sizeof(res)); + res.start =3D HPC3_CHIP0_BASE + offsetof(struct hpc3_regs, rtcregs); + res.end =3D res.start + sizeof(hpc3c0->rtcregs) - 1; + res.flags =3D IORESOURCE_MEM; + + return platform_device_register(&zilog_device); +} + +device_initcall(sgi_zilog_devinit); diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c index c2cae50f06f3..6e19c6713849 100644 --- a/drivers/tty/serial/ip22zilog.c +++ b/drivers/tty/serial/ip22zilog.c @@ -30,6 +30,7 @@ #include #include #include +#include =20 #include #include @@ -50,8 +51,9 @@ #define ZSDELAY_LONG() udelay(20) #define ZS_WSYNC(channel) do { } while (0) =20 -#define NUM_IP22ZILOG 1 -#define NUM_CHANNELS (NUM_IP22ZILOG * 2) +#define NUM_CHANNELS 2 +#define CHANNEL_B 0 +#define CHANNEL_A 1 =20 #define ZS_CLOCK 3672000 /* Zilog input clock rate. */ #define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */ @@ -62,9 +64,6 @@ struct uart_ip22zilog_port { struct uart_port port; =20 - /* IRQ servicing chain. */ - struct uart_ip22zilog_port *next; - /* Current values of Zilog write registers. */ unsigned char curregs[NUM_ZSREGS]; =20 @@ -72,7 +71,6 @@ struct uart_ip22zilog_port { #define IP22ZILOG_FLAG_IS_CONS 0x00000004 #define IP22ZILOG_FLAG_IS_KGDB 0x00000008 #define IP22ZILOG_FLAG_MODEM_STATUS 0x00000010 -#define IP22ZILOG_FLAG_IS_CHANNEL_A 0x00000020 #define IP22ZILOG_FLAG_REGS_HELD 0x00000040 #define IP22ZILOG_FLAG_TX_STOPPED 0x00000080 #define IP22ZILOG_FLAG_TX_ACTIVE 0x00000100 @@ -84,6 +82,8 @@ struct uart_ip22zilog_port { unsigned char prev_status; }; =20 +static struct uart_ip22zilog_port ip22zilog_port_table[NUM_CHANNELS]; + #define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel *)((PORT)->me= mbase)) #define UART_ZILOG(PORT) ((struct uart_ip22zilog_port *)(PORT)) #define IP22ZILOG_GET_CURR_REG(PORT, REGNUM) \ @@ -93,7 +93,6 @@ struct uart_ip22zilog_port { #define ZS_IS_CONS(UP) ((UP)->flags & IP22ZILOG_FLAG_IS_CONS) #define ZS_IS_KGDB(UP) ((UP)->flags & IP22ZILOG_FLAG_IS_KGDB) #define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & IP22ZILOG_FLAG_MODEM_STAT= US) -#define ZS_IS_CHANNEL_A(UP) ((UP)->flags & IP22ZILOG_FLAG_IS_CHANNEL_A) #define ZS_REGS_HELD(UP) ((UP)->flags & IP22ZILOG_FLAG_REGS_HELD) #define ZS_TX_STOPPED(UP) ((UP)->flags & IP22ZILOG_FLAG_TX_STOPPED) #define ZS_TX_ACTIVE(UP) ((UP)->flags & IP22ZILOG_FLAG_TX_ACTIVE) @@ -423,60 +422,57 @@ static void ip22zilog_transmit_chars(struct uart_ip22= zilog_port *up, =20 static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) { - struct uart_ip22zilog_port *up =3D dev_id; + struct uart_ip22zilog_port *up; + struct zilog_channel *channel; + unsigned char r3; + bool push =3D false; =20 - while (up) { - struct zilog_channel *channel - =3D ZILOG_CHANNEL_FROM_PORT(&up->port); - unsigned char r3; - bool push =3D false; + up =3D &ip22zilog_port_table[CHANNEL_A]; + channel =3D ZILOG_CHANNEL_FROM_PORT(&up->port); =20 - uart_port_lock(&up->port); - r3 =3D read_zsreg(channel, R3); + uart_port_lock(&up->port); + r3 =3D read_zsreg(channel, R3); =20 - /* Channel A */ - if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { - writeb(RES_H_IUS, &channel->control); - ZSDELAY(); - ZS_WSYNC(channel); + /* Channel A */ + if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { + writeb(RES_H_IUS, &channel->control); + ZSDELAY(); + ZS_WSYNC(channel); =20 - if (r3 & CHARxIP) - push =3D ip22zilog_receive_chars(up, channel); - if (r3 & CHAEXT) - ip22zilog_status_handle(up, channel); - if (r3 & CHATxIP) - ip22zilog_transmit_chars(up, channel); - } - uart_port_unlock(&up->port); - - if (push) - tty_flip_buffer_push(&up->port.state->port); - - /* Channel B */ - up =3D up->next; - channel =3D ZILOG_CHANNEL_FROM_PORT(&up->port); - push =3D false; - - uart_port_lock(&up->port); - if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { - writeb(RES_H_IUS, &channel->control); - ZSDELAY(); - ZS_WSYNC(channel); - - if (r3 & CHBRxIP) - push =3D ip22zilog_receive_chars(up, channel); - if (r3 & CHBEXT) - ip22zilog_status_handle(up, channel); - if (r3 & CHBTxIP) - ip22zilog_transmit_chars(up, channel); - } - uart_port_unlock(&up->port); - - if (push) - tty_flip_buffer_push(&up->port.state->port); - - up =3D up->next; + if (r3 & CHARxIP) + push =3D ip22zilog_receive_chars(up, channel); + if (r3 & CHAEXT) + ip22zilog_status_handle(up, channel); + if (r3 & CHATxIP) + ip22zilog_transmit_chars(up, channel); } + uart_port_unlock(&up->port); + + if (push) + tty_flip_buffer_push(&up->port.state->port); + + /* Channel B */ + up =3D &ip22zilog_port_table[CHANNEL_B]; + channel =3D ZILOG_CHANNEL_FROM_PORT(&up->port); + push =3D false; + + uart_port_lock(&up->port); + if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { + writeb(RES_H_IUS, &channel->control); + ZSDELAY(); + ZS_WSYNC(channel); + + if (r3 & CHBRxIP) + push =3D ip22zilog_receive_chars(up, channel); + if (r3 & CHBEXT) + ip22zilog_status_handle(up, channel); + if (r3 & CHBTxIP) + ip22zilog_transmit_chars(up, channel); + } + uart_port_unlock(&up->port); + + if (push) + tty_flip_buffer_push(&up->port.state->port); =20 return IRQ_HANDLED; } @@ -692,16 +688,16 @@ static void __ip22zilog_reset(struct uart_ip22zilog_p= ort *up) udelay(100); } =20 - if (!ZS_IS_CHANNEL_A(up)) { - up++; - channel =3D ZILOG_CHANNEL_FROM_PORT(&up->port); - } + up =3D &ip22zilog_port_table[CHANNEL_A]; + channel =3D ZILOG_CHANNEL_FROM_PORT(&up->port); + write_zsreg(channel, R9, FHWRES); ZSDELAY_LONG(); (void) read_zsreg(channel, R0); =20 up->flags |=3D IP22ZILOG_FLAG_RESET_DONE; - up->next->flags |=3D IP22ZILOG_FLAG_RESET_DONE; + up =3D &ip22zilog_port_table[CHANNEL_B]; + up->flags |=3D IP22ZILOG_FLAG_RESET_DONE; } =20 static void __ip22zilog_startup(struct uart_ip22zilog_port *up) @@ -942,47 +938,6 @@ static const struct uart_ops ip22zilog_pops =3D { .verify_port =3D ip22zilog_verify_port, }; =20 -static struct uart_ip22zilog_port *ip22zilog_port_table; -static struct zilog_layout **ip22zilog_chip_regs; - -static struct uart_ip22zilog_port *ip22zilog_irq_chain; -static int zilog_irq =3D -1; - -static void * __init alloc_one_table(unsigned long size) -{ - return kzalloc(size, GFP_KERNEL); -} - -static void __init ip22zilog_alloc_tables(void) -{ - ip22zilog_port_table =3D (struct uart_ip22zilog_port *) - alloc_one_table(NUM_CHANNELS * sizeof(struct uart_ip22zilog_port)); - ip22zilog_chip_regs =3D (struct zilog_layout **) - alloc_one_table(NUM_IP22ZILOG * sizeof(struct zilog_layout *)); - - if (ip22zilog_port_table =3D=3D NULL || ip22zilog_chip_regs =3D=3D NULL) { - panic("IP22-Zilog: Cannot allocate IP22-Zilog tables."); - } -} - -/* Get the address of the registers for IP22-Zilog instance CHIP. */ -static struct zilog_layout * __init get_zs(int chip) -{ - unsigned long base; - - if (chip < 0 || chip >=3D NUM_IP22ZILOG) { - panic("IP22-Zilog: Illegal chip number %d in get_zs.", chip); - } - - /* Not probe-able, hard code it. */ - base =3D (unsigned long) &sgioc->uart; - - zilog_irq =3D SGI_SERIAL_IRQ; - request_mem_region(base, 8, "IP22-Zilog"); - - return (struct zilog_layout *) base; -} - #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ =20 #ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE @@ -1070,144 +1025,123 @@ static struct uart_driver ip22zilog_reg =3D { #endif }; =20 -static void __init ip22zilog_prepare(void) +static void __init ip22zilog_prepare(struct uart_ip22zilog_port *up) { unsigned char sysrq_on =3D IS_ENABLED(CONFIG_SERIAL_IP22_ZILOG_CONSOLE); - struct uart_ip22zilog_port *up; - struct zilog_layout *rp; - int channel, chip; + int brg; =20 - /* - * Temporary fix. - */ - for (channel =3D 0; channel < NUM_CHANNELS; channel++) - spin_lock_init(&ip22zilog_port_table[channel].port.lock); + spin_lock_init(&up->port.lock); =20 - ip22zilog_irq_chain =3D &ip22zilog_port_table[NUM_CHANNELS - 1]; - up =3D &ip22zilog_port_table[0]; - for (channel =3D NUM_CHANNELS - 1 ; channel > 0; channel--) - up[channel].next =3D &up[channel - 1]; - up[channel].next =3D NULL; + up->port.iotype =3D UPIO_MEM; + up->port.uartclk =3D ZS_CLOCK; + up->port.fifosize =3D 1; + up->port.has_sysrq =3D sysrq_on; + up->port.ops =3D &ip22zilog_pops; + up->port.type =3D PORT_IP22ZILOG; =20 - for (chip =3D 0; chip < NUM_IP22ZILOG; chip++) { - if (!ip22zilog_chip_regs[chip]) { - ip22zilog_chip_regs[chip] =3D rp =3D get_zs(chip); - - up[(chip * 2) + 0].port.membase =3D (char *) &rp->channelB; - up[(chip * 2) + 1].port.membase =3D (char *) &rp->channelA; - - /* In theory mapbase is the physical address ... */ - up[(chip * 2) + 0].port.mapbase =3D - (unsigned long) ioremap((unsigned long) &rp->channelB, 8); - up[(chip * 2) + 1].port.mapbase =3D - (unsigned long) ioremap((unsigned long) &rp->channelA, 8); - } - - /* Channel A */ - up[(chip * 2) + 0].port.iotype =3D UPIO_MEM; - up[(chip * 2) + 0].port.irq =3D zilog_irq; - up[(chip * 2) + 0].port.uartclk =3D ZS_CLOCK; - up[(chip * 2) + 0].port.fifosize =3D 1; - up[(chip * 2) + 0].port.has_sysrq =3D sysrq_on; - up[(chip * 2) + 0].port.ops =3D &ip22zilog_pops; - up[(chip * 2) + 0].port.type =3D PORT_IP22ZILOG; - up[(chip * 2) + 0].port.flags =3D 0; - up[(chip * 2) + 0].port.line =3D (chip * 2) + 0; - up[(chip * 2) + 0].flags =3D 0; - - /* Channel B */ - up[(chip * 2) + 1].port.iotype =3D UPIO_MEM; - up[(chip * 2) + 1].port.irq =3D zilog_irq; - up[(chip * 2) + 1].port.uartclk =3D ZS_CLOCK; - up[(chip * 2) + 1].port.fifosize =3D 1; - up[(chip * 2) + 1].port.has_sysrq =3D sysrq_on; - up[(chip * 2) + 1].port.ops =3D &ip22zilog_pops; - up[(chip * 2) + 1].port.type =3D PORT_IP22ZILOG; - up[(chip * 2) + 1].port.line =3D (chip * 2) + 1; - up[(chip * 2) + 1].flags |=3D IP22ZILOG_FLAG_IS_CHANNEL_A; - } - - for (channel =3D 0; channel < NUM_CHANNELS; channel++) { - struct uart_ip22zilog_port *up =3D &ip22zilog_port_table[channel]; - int brg; - - /* Normal serial TTY. */ - up->parity_mask =3D 0xff; - up->curregs[R1] =3D EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; - up->curregs[R4] =3D PAR_EVEN | X16CLK | SB1; - up->curregs[R3] =3D RxENAB | Rx8; - up->curregs[R5] =3D TxENAB | Tx8; - up->curregs[R9] =3D NV | MIE; - up->curregs[R10] =3D NRZ; - up->curregs[R11] =3D TCBR | RCBR; - brg =3D BPS_TO_BRG(9600, ZS_CLOCK / ZS_CLOCK_DIVISOR); - up->curregs[R12] =3D (brg & 0xff); - up->curregs[R13] =3D (brg >> 8) & 0xff; - up->curregs[R14] =3D BRENAB; - } + /* Normal serial TTY. */ + up->parity_mask =3D 0xff; + up->curregs[R1] =3D EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; + up->curregs[R4] =3D PAR_EVEN | X16CLK | SB1; + up->curregs[R3] =3D RxENAB | Rx8; + up->curregs[R5] =3D TxENAB | Tx8; + up->curregs[R9] =3D NV | MIE; + up->curregs[R10] =3D NRZ; + up->curregs[R11] =3D TCBR | RCBR; + brg =3D BPS_TO_BRG(9600, ZS_CLOCK / ZS_CLOCK_DIVISOR); + up->curregs[R12] =3D (brg & 0xff); + up->curregs[R13] =3D (brg >> 8) & 0xff; + up->curregs[R14] =3D BRENAB; } =20 -static int __init ip22zilog_ports_init(void) +static int ip22zilog_probe(struct platform_device *pdev) { - int ret; + struct uart_ip22zilog_port *up; + char __iomem *membase; + struct resource *res; + int irq; + int i; =20 - printk(KERN_INFO "Serial: IP22 Zilog driver (%d chips).\n", NUM_IP22ZILOG= ); + up =3D &ip22zilog_port_table[CHANNEL_B]; + if (up->port.dev) + return -ENOSPC; =20 - ip22zilog_prepare(); + irq =3D platform_get_irq(pdev, 0); + if (irq < 0) + return irq; =20 - if (request_irq(zilog_irq, ip22zilog_interrupt, 0, - "IP22-Zilog", ip22zilog_irq_chain)) { + membase =3D devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(membase)) + return PTR_ERR(membase); + + ip22zilog_prepare(up); + + up->port.mapbase =3D res->start + offsetof(struct zilog_layout, channelB); + up->port.membase =3D membase + offsetof(struct zilog_layout, channelB); + up->port.line =3D 0; + up->port.dev =3D &pdev->dev; + up->port.irq =3D irq; + + up =3D &ip22zilog_port_table[CHANNEL_A]; + ip22zilog_prepare(up); + + up->port.mapbase =3D res->start + offsetof(struct zilog_layout, channelA); + up->port.membase =3D membase + offsetof(struct zilog_layout, channelA); + up->port.line =3D 1; + up->port.dev =3D &pdev->dev; + up->port.irq =3D irq; + + if (request_irq(irq, ip22zilog_interrupt, 0, + "IP22-Zilog", NULL)) { panic("IP22-Zilog: Unable to register zs interrupt handler.\n"); } =20 - ret =3D uart_register_driver(&ip22zilog_reg); - if (ret =3D=3D 0) { - int i; - - for (i =3D 0; i < NUM_CHANNELS; i++) { - struct uart_ip22zilog_port *up =3D &ip22zilog_port_table[i]; - - uart_add_one_port(&ip22zilog_reg, &up->port); - } - } - - return ret; -} - -static int __init ip22zilog_init(void) -{ - /* IP22 Zilog setup is hard coded, no probing to do. */ - ip22zilog_alloc_tables(); - ip22zilog_ports_init(); + for (i =3D 0; i < NUM_CHANNELS; i++) + uart_add_one_port(&ip22zilog_reg, + &ip22zilog_port_table[i].port); =20 return 0; } =20 -static void __exit ip22zilog_exit(void) +static void ip22zilog_remove(struct platform_device *pdev) { int i; - struct uart_ip22zilog_port *up; =20 for (i =3D 0; i < NUM_CHANNELS; i++) { - up =3D &ip22zilog_port_table[i]; - - uart_remove_one_port(&ip22zilog_reg, &up->port); + uart_remove_one_port(&ip22zilog_reg, + &ip22zilog_port_table[i].port); + ip22zilog_port_table[i].port.dev =3D NULL; } +} =20 - /* Free IO mem */ - up =3D &ip22zilog_port_table[0]; - for (i =3D 0; i < NUM_IP22ZILOG; i++) { - if (up[(i * 2) + 0].port.mapbase) { - iounmap((void*)up[(i * 2) + 0].port.mapbase); - up[(i * 2) + 0].port.mapbase =3D 0; - } - if (up[(i * 2) + 1].port.mapbase) { - iounmap((void*)up[(i * 2) + 1].port.mapbase); - up[(i * 2) + 1].port.mapbase =3D 0; - } +static struct platform_driver ip22zilog_driver =3D { + .probe =3D ip22zilog_probe, + .remove =3D ip22zilog_remove, + .driver =3D { + .name =3D "ip22zilog" } +}; =20 +static int __init ip22zilog_init(void) +{ + int ret; + + ret =3D uart_register_driver(&ip22zilog_reg); + if (ret) + return ret; + + ret =3D platform_driver_register(&ip22zilog_driver); + if (ret) + uart_unregister_driver(&ip22zilog_reg); + + return ret; + +} + +static void __exit ip22zilog_exit(void) +{ uart_unregister_driver(&ip22zilog_reg); + platform_driver_unregister(&ip22zilog_driver); } =20 module_init(ip22zilog_init); --=20 2.43.0