Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc, of_serial: Endianness issues setting up the serial ports

The speed and clock of the serial ports is retrieved from the device
tree in both the PowerPC legacy serial code and the Open Firmware serial
driver, therefore they need to handle the fact that the device tree is
always big endian, while the CPU may not be.

Also fix other device tree references in the legacy serial code.

Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>

authored by

Ian Munsie and committed by
Grant Likely
f14362d1 25485584

+17 -17
+11 -11
arch/powerpc/kernel/legacy_serial.c
··· 52 52 phys_addr_t taddr, unsigned long irq, 53 53 upf_t flags, int irq_check_parent) 54 54 { 55 - const u32 *clk, *spd; 55 + const __be32 *clk, *spd; 56 56 u32 clock = BASE_BAUD * 16; 57 57 int index; 58 58 59 59 /* get clock freq. if present */ 60 60 clk = of_get_property(np, "clock-frequency", NULL); 61 61 if (clk && *clk) 62 - clock = *clk; 62 + clock = be32_to_cpup(clk); 63 63 64 64 /* get default speed if present */ 65 65 spd = of_get_property(np, "current-speed", NULL); ··· 109 109 legacy_serial_infos[index].taddr = taddr; 110 110 legacy_serial_infos[index].np = of_node_get(np); 111 111 legacy_serial_infos[index].clock = clock; 112 - legacy_serial_infos[index].speed = spd ? *spd : 0; 112 + legacy_serial_infos[index].speed = spd ? be32_to_cpup(spd) : 0; 113 113 legacy_serial_infos[index].irq_check_parent = irq_check_parent; 114 114 115 115 printk(KERN_DEBUG "Found legacy serial port %d for %s\n", ··· 168 168 static int __init add_legacy_isa_port(struct device_node *np, 169 169 struct device_node *isa_brg) 170 170 { 171 - const u32 *reg; 171 + const __be32 *reg; 172 172 const char *typep; 173 173 int index = -1; 174 174 u64 taddr; ··· 181 181 return -1; 182 182 183 183 /* Verify it's an IO port, we don't support anything else */ 184 - if (!(reg[0] & 0x00000001)) 184 + if (!(be32_to_cpu(reg[0]) & 0x00000001)) 185 185 return -1; 186 186 187 187 /* Now look for an "ibm,aix-loc" property that gives us ordering ··· 202 202 taddr = 0; 203 203 204 204 /* Add port, irq will be dealt with later */ 205 - return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, 205 + return add_legacy_port(np, index, UPIO_PORT, be32_to_cpu(reg[1]), taddr, 206 206 NO_IRQ, UPF_BOOT_AUTOCONF, 0); 207 207 208 208 } ··· 251 251 * we get to their "reg" property 252 252 */ 253 253 if (np != pci_dev) { 254 - const u32 *reg = of_get_property(np, "reg", NULL); 255 - if (reg && (*reg < 4)) 256 - index = lindex = *reg; 254 + const __be32 *reg = of_get_property(np, "reg", NULL); 255 + if (reg && (be32_to_cpup(reg) < 4)) 256 + index = lindex = be32_to_cpup(reg); 257 257 } 258 258 259 259 /* Local index means it's the Nth port in the PCI chip. Unfortunately ··· 507 507 struct device_node *prom_stdout = NULL; 508 508 int i, speed = 0, offset = 0; 509 509 const char *name; 510 - const u32 *spd; 510 + const __be32 *spd; 511 511 512 512 DBG(" -> check_legacy_serial_console()\n"); 513 513 ··· 547 547 } 548 548 spd = of_get_property(prom_stdout, "current-speed", NULL); 549 549 if (spd) 550 - speed = *spd; 550 + speed = be32_to_cpup(spd); 551 551 552 552 if (strcmp(name, "serial") != 0) 553 553 goto not_found;
+6 -6
drivers/serial/of_serial.c
··· 31 31 { 32 32 struct resource resource; 33 33 struct device_node *np = ofdev->dev.of_node; 34 - const unsigned int *clk, *spd; 35 - const u32 *prop; 34 + const __be32 *clk, *spd; 35 + const __be32 *prop; 36 36 int ret, prop_size; 37 37 38 38 memset(port, 0, sizeof *port); ··· 55 55 /* Check for shifted address mapping */ 56 56 prop = of_get_property(np, "reg-offset", &prop_size); 57 57 if (prop && (prop_size == sizeof(u32))) 58 - port->mapbase += *prop; 58 + port->mapbase += be32_to_cpup(prop); 59 59 60 60 /* Check for registers offset within the devices address range */ 61 61 prop = of_get_property(np, "reg-shift", &prop_size); 62 62 if (prop && (prop_size == sizeof(u32))) 63 - port->regshift = *prop; 63 + port->regshift = be32_to_cpup(prop); 64 64 65 65 port->irq = irq_of_parse_and_map(np, 0); 66 66 port->iotype = UPIO_MEM; 67 67 port->type = type; 68 - port->uartclk = *clk; 68 + port->uartclk = be32_to_cpup(clk); 69 69 port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP 70 70 | UPF_FIXED_PORT | UPF_FIXED_TYPE; 71 71 port->dev = &ofdev->dev; 72 72 /* If current-speed was set, then try not to change it. */ 73 73 if (spd) 74 - port->custom_divisor = *clk / (16 * (*spd)); 74 + port->custom_divisor = be32_to_cpup(clk) / (16 * (be32_to_cpup(spd))); 75 75 76 76 return 0; 77 77 }