arch/mips/loongson64/env.c

Source file repositories/reference/linux-study-clean/arch/mips/loongson64/env.c

File Facts

System
Linux kernel
Corpus path
arch/mips/loongson64/env.c
Extension
.c
Size
10669 bytes
Lines
355
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!clk) {
			pr_warn("UART 0x%llx misses clock-frequency property\n",
				uart_addr);
			return -ENOENT;
		} else if (len != 4) {
			pr_warn("UART 0x%llx has invalid clock-frequency property\n",
				uart_addr);
			return -EINVAL;
		}

		fdt32_st(clk, uart_clk);

		return 0;
	}

	return -ENODEV;
}

static void __init lefi_fixup_fdt(struct system_loongson *system)
{
	static unsigned char fdt_buf[16 << 10] __initdata;
	struct uart_device *uartdev;
	bool is_loongson64g;
	u64 uart_base;
	int ret, i;

	ret = fdt_open_into(loongson_fdt_blob, fdt_buf, sizeof(fdt_buf));
	if (ret) {
		pr_err("Failed to open FDT to fix up\n");
		return;
	}

	is_loongson64g = (read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64G;

	for (i = 0; i < min(system->nr_uarts, MAX_UARTS); i++) {
		uartdev = &system->uarts[i];

		/*
		 * Some firmware does not set nr_uarts properly and passes empty
		 * items. Ignore them silently.
		 */
		if (uartdev->uart_base == 0)
			continue;

		/* Our DT only works with UPIO_MEM. */
		if (uartdev->iotype != UPIO_MEM) {
			pr_warn("Ignore UART 0x%llx with iotype %u passed by firmware\n",
				uartdev->uart_base, uartdev->iotype);
			continue;
		}

		ret = lefi_fixup_fdt_serial(fdt_buf, uartdev->uart_base,
					    uartdev->uartclk);
		/*
		 * LOONGSON64G's CPU serials are mapped to two different
		 * addresses, one full-featured but differs from
		 * previous generations, one fully compatible with them.
		 *
		 * It's unspecified that which mapping should uart_base refer
		 * to, thus we should try fixing up with both.
		 */
		if (ret == -ENODEV && is_loongson64g) {
			switch (uartdev->uart_base) {
			case 0x1fe00100:
				uart_base = 0x1fe001e0;
				break;
			case 0x1fe00110:
				uart_base = 0x1fe001e8;
				break;
			case 0x1fe001e0:
				uart_base = 0x1fe00100;
				break;
			case 0x1fe001e8:
				uart_base = 0x1fe00110;
				break;
			default:
				pr_err("Unexpected UART address 0x%llx passed by firmware\n",
				       uartdev->uart_base);
				ret = -EINVAL;
				goto err_fixup;
			}

			ret = lefi_fixup_fdt_serial(fdt_buf, uart_base,
						    uartdev->uartclk);
		}

err_fixup:
		if (ret)
			pr_err("Couldn't fix up FDT node for UART 0x%llx\n",
			       uartdev->uart_base);

Annotation

Implementation Notes