summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-12-14 16:20:48 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2020-12-14 16:20:48 -0800
commit0b03beface02d519693edb8020f9811c67d5c88f (patch)
treee69b63da6b4fa28fd70205187c699aecf1b1128e /drivers
parent2c075f38a708c578a752b738a45e8c26923eac2e (diff)
parent2ae92e8b9b7eb042ccb7e9fc7ea9431f211a1bd3 (diff)
Merge tag 'm68k-for-v5.11-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k
Pull m68k updates from Geert Uytterhoeven: - fix WARNING splat in pmac_zilog driver - fix ADB input device regression - assume maintainership for adb-iop and via-macii - minor fixes and improvements - defconfig updates * tag 'm68k-for-v5.11-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k: MAINTAINERS: Update m68k Mac entry macintosh/adb-iop: Send correct poll command macintosh/adb-iop: Always wait for reply message from IOP m68k: Fix WARNING splat in pmac_zilog driver m68k: Add a missing ELF_DETAILS in link script m68k: Drop redundant NOTES in link script m68k: mac: Update Kconfig help m68k: mac: Remove redundant VIA register writes m68k: mac: Remove dead code m68k: mac: Refactor iop_preinit() and iop_init() m68k: defconfig: Enable KUnit tests m68k: defconfig: Update defconfigs for v5.10-rc1 m68k: Remove unused mach_max_dma_address m68k: Avoid xchg() warning
Diffstat (limited to 'drivers')
-rw-r--r--drivers/macintosh/adb-iop.c56
-rw-r--r--drivers/tty/serial/pmac_zilog.c14
2 files changed, 47 insertions, 23 deletions
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c
index f3d1a460fbce..0ee327249150 100644
--- a/drivers/macintosh/adb-iop.c
+++ b/drivers/macintosh/adb-iop.c
@@ -25,6 +25,7 @@
static struct adb_request *current_req;
static struct adb_request *last_req;
static unsigned int autopoll_devs;
+static u8 autopoll_addr;
static enum adb_iop_state {
idle,
@@ -41,6 +42,11 @@ static int adb_iop_autopoll(int);
static void adb_iop_poll(void);
static int adb_iop_reset_bus(void);
+/* ADB command byte structure */
+#define ADDR_MASK 0xF0
+#define OP_MASK 0x0C
+#define TALK 0x0C
+
struct adb_driver adb_iop_driver = {
.name = "ISM IOP",
.probe = adb_iop_probe,
@@ -78,10 +84,7 @@ static void adb_iop_complete(struct iop_msg *msg)
local_irq_save(flags);
- if (current_req->reply_expected)
- adb_iop_state = awaiting_reply;
- else
- adb_iop_done();
+ adb_iop_state = awaiting_reply;
local_irq_restore(flags);
}
@@ -89,38 +92,52 @@ static void adb_iop_complete(struct iop_msg *msg)
/*
* Listen for ADB messages from the IOP.
*
- * This will be called when unsolicited messages (usually replies to TALK
- * commands or autopoll packets) are received.
+ * This will be called when unsolicited IOP messages are received.
+ * These IOP messages can carry ADB autopoll responses and also occur
+ * after explicit ADB commands.
*/
static void adb_iop_listen(struct iop_msg *msg)
{
struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
+ u8 addr = (amsg->cmd & ADDR_MASK) >> 4;
+ u8 op = amsg->cmd & OP_MASK;
unsigned long flags;
bool req_done = false;
local_irq_save(flags);
- /* Handle a timeout. Timeout packets seem to occur even after
- * we've gotten a valid reply to a TALK, presumably because of
- * autopolling.
+ /* Responses to Talk commands may be unsolicited as they are
+ * produced when the IOP polls devices. They are mostly timeouts.
*/
-
- if (amsg->flags & ADB_IOP_EXPLICIT) {
+ if (op == TALK && ((1 << addr) & autopoll_devs))
+ autopoll_addr = addr;
+
+ switch (amsg->flags & (ADB_IOP_EXPLICIT |
+ ADB_IOP_AUTOPOLL |
+ ADB_IOP_TIMEOUT)) {
+ case ADB_IOP_EXPLICIT:
+ case ADB_IOP_EXPLICIT | ADB_IOP_TIMEOUT:
if (adb_iop_state == awaiting_reply) {
struct adb_request *req = current_req;
- req->reply_len = amsg->count + 1;
- memcpy(req->reply, &amsg->cmd, req->reply_len);
+ if (req->reply_expected) {
+ req->reply_len = amsg->count + 1;
+ memcpy(req->reply, &amsg->cmd, req->reply_len);
+ }
req_done = true;
}
- } else if (!(amsg->flags & ADB_IOP_TIMEOUT)) {
- adb_input(&amsg->cmd, amsg->count + 1,
- amsg->flags & ADB_IOP_AUTOPOLL);
+ break;
+ case ADB_IOP_AUTOPOLL:
+ if (((1 << addr) & autopoll_devs) &&
+ amsg->cmd == ADB_READREG(addr, 0))
+ adb_input(&amsg->cmd, amsg->count + 1, 1);
+ break;
}
-
- msg->reply[0] = autopoll_devs ? ADB_IOP_AUTOPOLL : 0;
+ msg->reply[0] = autopoll_addr ? ADB_IOP_AUTOPOLL : 0;
+ msg->reply[1] = 0;
+ msg->reply[2] = autopoll_addr ? ADB_READREG(autopoll_addr, 0) : 0;
iop_complete_message(msg);
if (req_done)
@@ -233,6 +250,9 @@ static void adb_iop_set_ap_complete(struct iop_msg *msg)
struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
autopoll_devs = (amsg->data[1] << 8) | amsg->data[0];
+ if (autopoll_devs & (1 << autopoll_addr))
+ return;
+ autopoll_addr = autopoll_devs ? (ffs(autopoll_devs) - 1) : 0;
}
static int adb_iop_autopoll(int devs)
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index 063484b22523..d6aef8a1f0a4 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -1693,22 +1693,26 @@ static int __init pmz_probe(void)
#else
+/* On PCI PowerMacs, pmz_probe() does an explicit search of the OpenFirmware
+ * tree to obtain the device_nodes needed to start the console before the
+ * macio driver. On Macs without OpenFirmware, global platform_devices take
+ * the place of those device_nodes.
+ */
extern struct platform_device scc_a_pdev, scc_b_pdev;
static int __init pmz_init_port(struct uart_pmac_port *uap)
{
- struct resource *r_ports;
- int irq;
+ struct resource *r_ports, *r_irq;
r_ports = platform_get_resource(uap->pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(uap->pdev, 0);
- if (!r_ports || irq <= 0)
+ r_irq = platform_get_resource(uap->pdev, IORESOURCE_IRQ, 0);
+ if (!r_ports || !r_irq)
return -ENODEV;
uap->port.mapbase = r_ports->start;
uap->port.membase = (unsigned char __iomem *) r_ports->start;
uap->port.iotype = UPIO_MEM;
- uap->port.irq = irq;
+ uap->port.irq = r_irq->start;
uap->port.uartclk = ZS_CLOCK;
uap->port.fifosize = 1;
uap->port.ops = &pmz_pops;