Commit 571b7e69 authored by Paul Burton's avatar Paul Burton Committed by Ralf Baechle

MIPS: generic/yamon-dt: Pull YAMON DT shim code out of SEAD-3 board

In preparation for supporting other YAMON-using boards (Malta) & sharing
code to translate information from YAMON into device tree properties,
pull the code doing so for the kernel command line, system memory &
serial configuration out of the SEAD-3 board code.
Signed-off-by: default avatarPaul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/16181/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent efe4a1ac
...@@ -9,9 +9,17 @@ config LEGACY_BOARDS ...@@ -9,9 +9,17 @@ config LEGACY_BOARDS
kernel is booted without being provided with an FDT via the UHI kernel is booted without being provided with an FDT via the UHI
boot protocol. boot protocol.
config YAMON_DT_SHIM
bool
help
Select this from your board if the board uses the YAMON bootloader
and you wish to include code which helps translate various
YAMON-provided environment variables into a device tree properties.
config LEGACY_BOARD_SEAD3 config LEGACY_BOARD_SEAD3
bool "Support MIPS SEAD-3 boards" bool "Support MIPS SEAD-3 boards"
select LEGACY_BOARDS select LEGACY_BOARDS
select YAMON_DT_SHIM
help help
Enable this to include support for booting on MIPS SEAD-3 FPGA-based Enable this to include support for booting on MIPS SEAD-3 FPGA-based
development boards, which boot using a legacy boot protocol. development boards, which boot using a legacy boot protocol.
......
...@@ -12,5 +12,6 @@ obj-y += init.o ...@@ -12,5 +12,6 @@ obj-y += init.o
obj-y += irq.o obj-y += irq.o
obj-y += proc.o obj-y += proc.o
obj-$(CONFIG_YAMON_DT_SHIM) += yamon-dt.o
obj-$(CONFIG_LEGACY_BOARD_SEAD3) += board-sead3.o obj-$(CONFIG_LEGACY_BOARD_SEAD3) += board-sead3.o
obj-$(CONFIG_KEXEC) += kexec.o obj-$(CONFIG_KEXEC) += kexec.o
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <asm/fw/fw.h> #include <asm/fw/fw.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/machine.h> #include <asm/machine.h>
#include <asm/yamon-dt.h>
#define SEAD_CONFIG CKSEG1ADDR(0x1b100110) #define SEAD_CONFIG CKSEG1ADDR(0x1b100110)
#define SEAD_CONFIG_GIC_PRESENT BIT(1) #define SEAD_CONFIG_GIC_PRESENT BIT(1)
...@@ -33,98 +34,6 @@ static __init bool sead3_detect(void) ...@@ -33,98 +34,6 @@ static __init bool sead3_detect(void)
return (rev & MIPS_REVISION_MACHINE) == MIPS_REVISION_MACHINE_SEAD3; return (rev & MIPS_REVISION_MACHINE) == MIPS_REVISION_MACHINE_SEAD3;
} }
static __init int append_cmdline(void *fdt)
{
int err, chosen_off;
/* find or add chosen node */
chosen_off = fdt_path_offset(fdt, "/chosen");
if (chosen_off == -FDT_ERR_NOTFOUND)
chosen_off = fdt_path_offset(fdt, "/chosen@0");
if (chosen_off == -FDT_ERR_NOTFOUND)
chosen_off = fdt_add_subnode(fdt, 0, "chosen");
if (chosen_off < 0) {
pr_err("Unable to find or add DT chosen node: %d\n",
chosen_off);
return chosen_off;
}
err = fdt_setprop_string(fdt, chosen_off, "bootargs", fw_getcmdline());
if (err) {
pr_err("Unable to set bootargs property: %d\n", err);
return err;
}
return 0;
}
static __init int append_memory(void *fdt)
{
unsigned long phys_memsize, memsize;
__be32 mem_array[2];
int err, mem_off;
char *var;
/* find memory size from the bootloader environment */
var = fw_getenv("memsize");
if (var) {
err = kstrtoul(var, 0, &phys_memsize);
if (err) {
pr_err("Failed to read memsize env variable '%s'\n",
var);
return -EINVAL;
}
} else {
pr_warn("The bootloader didn't provide memsize: defaulting to 32MB\n");
phys_memsize = 32 << 20;
}
/* default to using all available RAM */
memsize = phys_memsize;
/* allow the user to override the usable memory */
var = strstr(arcs_cmdline, "memsize=");
if (var)
memsize = memparse(var + strlen("memsize="), NULL);
/* if the user says there's more RAM than we thought, believe them */
phys_memsize = max_t(unsigned long, phys_memsize, memsize);
/* find or add a memory node */
mem_off = fdt_path_offset(fdt, "/memory");
if (mem_off == -FDT_ERR_NOTFOUND)
mem_off = fdt_add_subnode(fdt, 0, "memory");
if (mem_off < 0) {
pr_err("Unable to find or add memory DT node: %d\n", mem_off);
return mem_off;
}
err = fdt_setprop_string(fdt, mem_off, "device_type", "memory");
if (err) {
pr_err("Unable to set memory node device_type: %d\n", err);
return err;
}
mem_array[0] = 0;
mem_array[1] = cpu_to_be32(phys_memsize);
err = fdt_setprop(fdt, mem_off, "reg", mem_array, sizeof(mem_array));
if (err) {
pr_err("Unable to set memory regs property: %d\n", err);
return err;
}
mem_array[0] = 0;
mem_array[1] = cpu_to_be32(memsize);
err = fdt_setprop(fdt, mem_off, "linux,usable-memory",
mem_array, sizeof(mem_array));
if (err) {
pr_err("Unable to set linux,usable-memory property: %d\n", err);
return err;
}
return 0;
}
static __init int remove_gic(void *fdt) static __init int remove_gic(void *fdt)
{ {
const unsigned int cpu_ehci_int = 2; const unsigned int cpu_ehci_int = 2;
...@@ -214,85 +123,6 @@ static __init int remove_gic(void *fdt) ...@@ -214,85 +123,6 @@ static __init int remove_gic(void *fdt)
return 0; return 0;
} }
static __init int serial_config(void *fdt)
{
const char *yamontty, *mode_var;
char mode_var_name[9], path[18], parity;
unsigned int uart, baud, stop_bits;
bool hw_flow;
int chosen_off, err;
yamontty = fw_getenv("yamontty");
if (!yamontty || !strcmp(yamontty, "tty0")) {
uart = 0;
} else if (!strcmp(yamontty, "tty1")) {
uart = 1;
} else {
pr_warn("yamontty environment variable '%s' invalid\n",
yamontty);
uart = 0;
}
baud = stop_bits = 0;
parity = 0;
hw_flow = false;
snprintf(mode_var_name, sizeof(mode_var_name), "modetty%u", uart);
mode_var = fw_getenv(mode_var_name);
if (mode_var) {
while (mode_var[0] >= '0' && mode_var[0] <= '9') {
baud *= 10;
baud += mode_var[0] - '0';
mode_var++;
}
if (mode_var[0] == ',')
mode_var++;
if (mode_var[0])
parity = mode_var[0];
if (mode_var[0] == ',')
mode_var++;
if (mode_var[0])
stop_bits = mode_var[0] - '0';
if (mode_var[0] == ',')
mode_var++;
if (!strcmp(mode_var, "hw"))
hw_flow = true;
}
if (!baud)
baud = 38400;
if (parity != 'e' && parity != 'n' && parity != 'o')
parity = 'n';
if (stop_bits != 7 && stop_bits != 8)
stop_bits = 8;
WARN_ON(snprintf(path, sizeof(path), "uart%u:%u%c%u%s",
uart, baud, parity, stop_bits,
hw_flow ? "r" : "") >= sizeof(path));
/* find or add chosen node */
chosen_off = fdt_path_offset(fdt, "/chosen");
if (chosen_off == -FDT_ERR_NOTFOUND)
chosen_off = fdt_path_offset(fdt, "/chosen@0");
if (chosen_off == -FDT_ERR_NOTFOUND)
chosen_off = fdt_add_subnode(fdt, 0, "chosen");
if (chosen_off < 0) {
pr_err("Unable to find or add DT chosen node: %d\n",
chosen_off);
return chosen_off;
}
err = fdt_setprop_string(fdt, chosen_off, "stdout-path", path);
if (err) {
pr_err("Unable to set stdout-path property: %d\n", err);
return err;
}
return 0;
}
static __init const void *sead3_fixup_fdt(const void *fdt, static __init const void *sead3_fixup_fdt(const void *fdt,
const void *match_data) const void *match_data)
{ {
...@@ -311,11 +141,11 @@ static __init const void *sead3_fixup_fdt(const void *fdt, ...@@ -311,11 +141,11 @@ static __init const void *sead3_fixup_fdt(const void *fdt,
if (err) if (err)
panic("Unable to open FDT: %d", err); panic("Unable to open FDT: %d", err);
err = append_cmdline(fdt_buf); err = yamon_dt_append_cmdline(fdt_buf);
if (err) if (err)
panic("Unable to patch FDT: %d", err); panic("Unable to patch FDT: %d", err);
err = append_memory(fdt_buf); err = yamon_dt_append_memory(fdt_buf);
if (err) if (err)
panic("Unable to patch FDT: %d", err); panic("Unable to patch FDT: %d", err);
...@@ -323,7 +153,7 @@ static __init const void *sead3_fixup_fdt(const void *fdt, ...@@ -323,7 +153,7 @@ static __init const void *sead3_fixup_fdt(const void *fdt,
if (err) if (err)
panic("Unable to patch FDT: %d", err); panic("Unable to patch FDT: %d", err);
err = serial_config(fdt_buf); err = yamon_dt_serial_config(fdt_buf);
if (err) if (err)
panic("Unable to patch FDT: %d", err); panic("Unable to patch FDT: %d", err);
......
/*
* Copyright (C) 2016 Imagination Technologies
* Author: Paul Burton <paul.burton@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#define pr_fmt(fmt) "yamon-dt: " fmt
#include <linux/bug.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/libfdt.h>
#include <linux/printk.h>
#include <asm/fw/fw.h>
__init int yamon_dt_append_cmdline(void *fdt)
{
int err, chosen_off;
/* find or add chosen node */
chosen_off = fdt_path_offset(fdt, "/chosen");
if (chosen_off == -FDT_ERR_NOTFOUND)
chosen_off = fdt_path_offset(fdt, "/chosen@0");
if (chosen_off == -FDT_ERR_NOTFOUND)
chosen_off = fdt_add_subnode(fdt, 0, "chosen");
if (chosen_off < 0) {
pr_err("Unable to find or add DT chosen node: %d\n",
chosen_off);
return chosen_off;
}
err = fdt_setprop_string(fdt, chosen_off, "bootargs", fw_getcmdline());
if (err) {
pr_err("Unable to set bootargs property: %d\n", err);
return err;
}
return 0;
}
__init int yamon_dt_append_memory(void *fdt)
{
unsigned long phys_memsize, memsize;
__be32 mem_array[2];
int err, mem_off;
char *var;
/* find memory size from the bootloader environment */
var = fw_getenv("memsize");
if (var) {
err = kstrtoul(var, 0, &phys_memsize);
if (err) {
pr_err("Failed to read memsize env variable '%s'\n",
var);
return -EINVAL;
}
} else {
pr_warn("The bootloader didn't provide memsize: defaulting to 32MB\n");
phys_memsize = 32 << 20;
}
/* default to using all available RAM */
memsize = phys_memsize;
/* allow the user to override the usable memory */
var = strstr(arcs_cmdline, "memsize=");
if (var)
memsize = memparse(var + strlen("memsize="), NULL);
/* if the user says there's more RAM than we thought, believe them */
phys_memsize = max_t(unsigned long, phys_memsize, memsize);
/* find or add a memory node */
mem_off = fdt_path_offset(fdt, "/memory");
if (mem_off == -FDT_ERR_NOTFOUND)
mem_off = fdt_add_subnode(fdt, 0, "memory");
if (mem_off < 0) {
pr_err("Unable to find or add memory DT node: %d\n", mem_off);
return mem_off;
}
err = fdt_setprop_string(fdt, mem_off, "device_type", "memory");
if (err) {
pr_err("Unable to set memory node device_type: %d\n", err);
return err;
}
mem_array[0] = 0;
mem_array[1] = cpu_to_be32(phys_memsize);
err = fdt_setprop(fdt, mem_off, "reg", mem_array, sizeof(mem_array));
if (err) {
pr_err("Unable to set memory regs property: %d\n", err);
return err;
}
mem_array[0] = 0;
mem_array[1] = cpu_to_be32(memsize);
err = fdt_setprop(fdt, mem_off, "linux,usable-memory",
mem_array, sizeof(mem_array));
if (err) {
pr_err("Unable to set linux,usable-memory property: %d\n", err);
return err;
}
return 0;
}
__init int yamon_dt_serial_config(void *fdt)
{
const char *yamontty, *mode_var;
char mode_var_name[9], path[18], parity;
unsigned int uart, baud, stop_bits;
bool hw_flow;
int chosen_off, err;
yamontty = fw_getenv("yamontty");
if (!yamontty || !strcmp(yamontty, "tty0")) {
uart = 0;
} else if (!strcmp(yamontty, "tty1")) {
uart = 1;
} else {
pr_warn("yamontty environment variable '%s' invalid\n",
yamontty);
uart = 0;
}
baud = stop_bits = 0;
parity = 0;
hw_flow = false;
snprintf(mode_var_name, sizeof(mode_var_name), "modetty%u", uart);
mode_var = fw_getenv(mode_var_name);
if (mode_var) {
while (mode_var[0] >= '0' && mode_var[0] <= '9') {
baud *= 10;
baud += mode_var[0] - '0';
mode_var++;
}
if (mode_var[0] == ',')
mode_var++;
if (mode_var[0])
parity = mode_var[0];
if (mode_var[0] == ',')
mode_var++;
if (mode_var[0])
stop_bits = mode_var[0] - '0';
if (mode_var[0] == ',')
mode_var++;
if (!strcmp(mode_var, "hw"))
hw_flow = true;
}
if (!baud)
baud = 38400;
if (parity != 'e' && parity != 'n' && parity != 'o')
parity = 'n';
if (stop_bits != 7 && stop_bits != 8)
stop_bits = 8;
WARN_ON(snprintf(path, sizeof(path), "uart%u:%u%c%u%s",
uart, baud, parity, stop_bits,
hw_flow ? "r" : "") >= sizeof(path));
/* find or add chosen node */
chosen_off = fdt_path_offset(fdt, "/chosen");
if (chosen_off == -FDT_ERR_NOTFOUND)
chosen_off = fdt_path_offset(fdt, "/chosen@0");
if (chosen_off == -FDT_ERR_NOTFOUND)
chosen_off = fdt_add_subnode(fdt, 0, "chosen");
if (chosen_off < 0) {
pr_err("Unable to find or add DT chosen node: %d\n",
chosen_off);
return chosen_off;
}
err = fdt_setprop_string(fdt, chosen_off, "stdout-path", path);
if (err) {
pr_err("Unable to set stdout-path property: %d\n", err);
return err;
}
return 0;
}
/*
* Copyright (C) 2016 Imagination Technologies
* Author: Paul Burton <paul.burton@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __MIPS_ASM_YAMON_DT_H__
#define __MIPS_ASM_YAMON_DT_H__
/**
* yamon_dt_append_cmdline() - Append YAMON-provided command line to /chosen
* @fdt: the FDT blob
*
* Write the YAMON-provided command line to the bootargs property of the
* /chosen node in @fdt.
*
* Return: 0 on success, else -errno
*/
extern __init int yamon_dt_append_cmdline(void *fdt);
/**
* yamon_dt_append_memory() - Append YAMON-provided memory info to /memory
* @fdt: the FDT blob
*
* Generate a /memory node in @fdt based upon memory size information provided
* by YAMON in its environment.
*
* Return: 0 on success, else -errno
*/
extern __init int yamon_dt_append_memory(void *fdt);
/**
* yamon_dt_serial_config() - Append YAMON-provided serial config to /chosen
* @fdt: the FDT blob
*
* Generate a stdout-path property in the /chosen node of @fdt, based upon
* information provided in the YAMON environment about the UART configuration
* of the system.
*
* Return: 0 on success, else -errno
*/
extern __init int yamon_dt_serial_config(void *fdt);
#endif /* __MIPS_ASM_YAMON_DT_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment