Commit 74f19946 authored by Olof Johansson's avatar Olof Johansson

Merge tag 'renesas-boards-for-v3.12' of...

Merge tag 'renesas-boards-for-v3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas into next/boards

From Simon Horman:
Renesas ARM-based SoC board updates for v3.12

* ape6evm: Add SDHI and MMCIF support
* lager: Add MMCIF support
* armadillo800eva: Add DMA support for MMCIF

* tag 'renesas-boards-for-v3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas: (54 commits)
  ARM: shmobile: ape6evm: add SDHI interfaces
  ARM: shmobile: ape6evm: add MMCIF support
  ARM: shmobile: select the fixed regulator driver on BockW
  ARM: shmobile: lager: add MMCIF support
  ARM: shmobile: armadillo800eva: add DMA support to MMCIF
  ARM: shmobile: Setup r8a7790 arch timer based on MD pins
  ARM: shmobile: Introduce r8a7790_read_mode_pins()
  ARM: shmobile: r8a7740: add MMCIF DMA definitions
  ARM: shmobile: Disconnect EMEV2 SMP code from clocks
  ARM: shmobile: Make r8a73a4 Arch timer optional
  ARM: shmobile: Add r8a73a4 CMT10 clock event
  ARM: shmobile: Make r8a7790 Arch timer optional
  ARM: shmobile: Add r8a7790 CMT00 clock event
  ARM: shmobile: Sort r8a7790 MSTP entries
  ARM: shmobile: r8a73a4: add clocks for I2C controllers
  ARM: shmobile: r8a73a4: add Z2 clock support
  ARM: shmobile: r8a73a4: safeguard against wrong clk_set_rate() uses
  ARM: shmobile: r8a73a4: implement CPU clock scaling for CPUFreq
  ARM: shmobile: r8a73a4: wait for completion when kicking the clock
  ARM: shmobile: r8a7790: add thermal driver support
  ...
Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 13b83799 f79d68da
......@@ -183,6 +183,7 @@ dtb-$(CONFIG_ARCH_U8500) += snowball.dtb \
ccu9540.dtb
dtb-$(CONFIG_ARCH_S3C24XX) += s3c2416-smdk2416.dtb
dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
emev2-kzm9d-reference.dtb \
r8a7740-armadillo800eva.dtb \
r8a7778-bockw.dtb \
r8a7740-armadillo800eva-reference.dtb \
......
/*
* Device Tree Source for the KZM9D board
*
* Copyright (C) 2013 Renesas Solutions Corp.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
/dts-v1/;
/include/ "emev2.dtsi"
/ {
model = "EMEV2 KZM9D Board";
compatible = "renesas,kzm9d-reference", "renesas,emev2";
memory {
device_type = "memory";
reg = <0x40000000 0x8000000>;
};
chosen {
bootargs = "console=ttyS1,115200n81 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096";
};
reg_1p8v: regulator@0 {
compatible = "regulator-fixed";
regulator-name = "fixed-1.8V";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
regulator-boot-on;
};
reg_3p3v: regulator@1 {
compatible = "regulator-fixed";
regulator-name = "fixed-3.3V";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
lan9220@20000000 {
compatible = "smsc,lan9220", "smsc,lan9115";
reg = <0x20000000 0x10000>;
phy-mode = "mii";
interrupt-parent = <&gpio0>;
interrupts = <1 1>; /* active high */
reg-io-width = <4>;
smsc,irq-active-high;
smsc,irq-push-pull;
vddvario-supply = <&reg_1p8v>;
vdd33a-supply = <&reg_3p3v>;
};
};
......@@ -21,6 +21,6 @@ memory {
};
chosen {
bootargs = "console=tty0 console=ttyS1,115200n81 earlyprintk=serial8250-em.1,115200n81 mem=128M@0x40000000 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096";
bootargs = "console=ttyS1,115200n81 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096";
};
};
......@@ -14,6 +14,14 @@ / {
compatible = "renesas,emev2";
interrupt-parent = <&gic>;
aliases {
gpio0 = &gpio0;
gpio1 = &gpio1;
gpio2 = &gpio2;
gpio3 = &gpio3;
gpio4 = &gpio4;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
......@@ -67,4 +75,55 @@ uart@e1050000 {
reg = <0xe1050000 0x38>;
interrupts = <0 11 0>;
};
gpio0: gpio@e0050000 {
compatible = "renesas,em-gio";
reg = <0xe0050000 0x2c>, <0xe0050040 0x20>;
interrupts = <0 67 0>, <0 68 0>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <32>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio1: gpio@e0050080 {
compatible = "renesas,em-gio";
reg = <0xe0050080 0x2c>, <0xe00500c0 0x20>;
interrupts = <0 69 0>, <0 70 0>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <32>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio2: gpio@e0050100 {
compatible = "renesas,em-gio";
reg = <0xe0050100 0x2c>, <0xe0050140 0x20>;
interrupts = <0 71 0>, <0 72 0>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <32>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio3: gpio@e0050180 {
compatible = "renesas,em-gio";
reg = <0xe0050180 0x2c>, <0xe00501c0 0x20>;
interrupts = <0 73 0>, <0 74 0>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <32>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio4: gpio@e0050200 {
compatible = "renesas,em-gio";
reg = <0xe0050200 0x2c>, <0xe0050240 0x20>;
interrupts = <0 75 0>, <0 76 0>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <31>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
......@@ -50,3 +50,25 @@ ethernet@8000000 {
};
};
};
&i2c5 {
vdd_dvfs: max8973@1b {
compatible = "maxim,max8973";
reg = <0x1b>;
regulator-min-microvolt = <935000>;
regulator-max-microvolt = <1200000>;
regulator-boot-on;
regulator-always-on;
};
};
&cpu0 {
cpu0-supply = <&vdd_dvfs>;
operating-points = <
/* kHz uV */
1950000 1115000
1462500 995000
>;
voltage-tolerance = <1>; /* 1% */
};
......@@ -85,4 +85,130 @@ thermal@e61f0000 {
interrupt-parent = <&gic>;
interrupts = <0 69 4>;
};
i2c0: i2c@e6500000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,rmobile-iic";
reg = <0 0xe6500000 0 0x428>;
interrupt-parent = <&gic>;
interrupts = <0 174 0x4>;
};
i2c1: i2c@e6510000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,rmobile-iic";
reg = <0 0xe6510000 0 0x428>;
interrupt-parent = <&gic>;
interrupts = <0 175 0x4>;
};
i2c2: i2c@e6520000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,rmobile-iic";
reg = <0 0xe6520000 0 0x428>;
interrupt-parent = <&gic>;
interrupts = <0 176 0x4>;
};
i2c3: i2c@e6530000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,rmobile-iic";
reg = <0 0xe6530000 0 0x428>;
interrupt-parent = <&gic>;
interrupts = <0 177 0x4>;
};
i2c4: i2c@e6540000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,rmobile-iic";
reg = <0 0xe6540000 0 0x428>;
interrupt-parent = <&gic>;
interrupts = <0 178 0x4>;
};
i2c5: i2c@e60b0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,rmobile-iic";
reg = <0 0xe60b0000 0 0x428>;
interrupt-parent = <&gic>;
interrupts = <0 179 0x4>;
};
i2c6: i2c@e6550000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,rmobile-iic";
reg = <0 0xe6550000 0 0x428>;
interrupt-parent = <&gic>;
interrupts = <0 184 0x4>;
};
i2c7: i2c@e6560000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,rmobile-iic";
reg = <0 0xe6560000 0 0x428>;
interrupt-parent = <&gic>;
interrupts = <0 185 0x4>;
};
i2c8: i2c@e6570000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,rmobile-iic";
reg = <0 0xe6570000 0 0x428>;
interrupt-parent = <&gic>;
interrupts = <0 173 0x4>;
};
mmcif0: mmcif@ee200000 {
compatible = "renesas,sh-mmcif";
reg = <0 0xee200000 0 0x80>;
interrupt-parent = <&gic>;
interrupts = <0 169 0x4>;
reg-io-width = <4>;
status = "disabled";
};
mmcif1: mmcif@ee220000 {
compatible = "renesas,sh-mmcif";
reg = <0 0xee220000 0 0x80>;
interrupt-parent = <&gic>;
interrupts = <0 170 0x4>;
reg-io-width = <4>;
status = "disabled";
};
sdhi0: sdhi@ee100000 {
compatible = "renesas,r8a73a4-sdhi";
reg = <0 0xee100000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 165 4>;
cap-sd-highspeed;
status = "disabled";
};
sdhi1: sdhi@ee120000 {
compatible = "renesas,r8a73a4-sdhi";
reg = <0 0xee120000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 166 4>;
cap-sd-highspeed;
status = "disabled";
};
sdhi2: sdhi@ee140000 {
compatible = "renesas,r8a73a4-sdhi";
reg = <0 0xee140000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 167 4>;
cap-sd-highspeed;
status = "disabled";
};
};
......@@ -54,4 +54,58 @@ irqc0: interrupt-controller@e61c0000 {
interrupt-parent = <&gic>;
interrupts = <0 0 4>, <0 1 4>, <0 2 4>, <0 3 4>;
};
mmcif0: mmcif@ee200000 {
compatible = "renesas,sh-mmcif";
reg = <0 0xee200000 0 0x80>;
interrupt-parent = <&gic>;
interrupts = <0 169 0x4>;
reg-io-width = <4>;
status = "disabled";
};
mmcif1: mmcif@ee220000 {
compatible = "renesas,sh-mmcif";
reg = <0 0xee220000 0 0x80>;
interrupt-parent = <&gic>;
interrupts = <0 170 0x4>;
reg-io-width = <4>;
status = "disabled";
};
sdhi0: sdhi@ee100000 {
compatible = "renesas,r8a7790-sdhi";
reg = <0 0xee100000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 165 4>;
cap-sd-highspeed;
status = "disabled";
};
sdhi1: sdhi@ee120000 {
compatible = "renesas,r8a7790-sdhi";
reg = <0 0xee120000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 166 4>;
cap-sd-highspeed;
status = "disabled";
};
sdhi2: sdhi@ee140000 {
compatible = "renesas,r8a7790-sdhi";
reg = <0 0xee140000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 167 4>;
cap-sd-highspeed;
status = "disabled";
};
sdhi3: sdhi@ee160000 {
compatible = "renesas,r8a7790-sdhi";
reg = <0 0xee160000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 168 4>;
cap-sd-highspeed;
status = "disabled";
};
};
......@@ -23,9 +23,10 @@ config ARCH_R8A73A4
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARM_GIC
select CPU_V7
select HAVE_ARM_ARCH_TIMER
select SH_CLK_CPG
select RENESAS_IRQC
select ARCH_HAS_CPUFREQ
select ARCH_HAS_OPP
config ARCH_R8A7740
bool "R-Mobile A1 (R8A77400)"
......@@ -59,7 +60,6 @@ config ARCH_R8A7790
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARM_GIC
select CPU_V7
select HAVE_ARM_ARCH_TIMER
select SH_CLK_CPG
select RENESAS_IRQC
......@@ -124,6 +124,7 @@ config MACH_BOCKW
depends on ARCH_R8A7778
select ARCH_REQUIRE_GPIOLIB
select RENESAS_INTC_IRQPIN
select REGULATOR_FIXED_VOLTAGE if REGULATOR
select USE_OF
config MACH_MARZEN
......@@ -156,6 +157,18 @@ config MACH_KZM9D
select REGULATOR_FIXED_VOLTAGE if REGULATOR
select USE_OF
config MACH_KZM9D_REFERENCE
bool "KZM9D board - Reference Device Tree Implementation"
depends on ARCH_EMEV2
select REGULATOR_FIXED_VOLTAGE if REGULATOR
select USE_OF
---help---
Use reference implementation of KZM9D board support
which makes a greater use of device tree at the expense
of not supporting a number of devices.
This is intended to aid developers
config MACH_KZM9G
bool "KZM-A9-GT board"
depends on ARCH_SH73A0
......
......@@ -46,6 +46,7 @@ obj-$(CONFIG_MACH_LAGER) += board-lager.o
obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o
obj-$(CONFIG_MACH_ARMADILLO800EVA_REFERENCE) += board-armadillo800eva-reference.o
obj-$(CONFIG_MACH_KZM9D) += board-kzm9d.o
obj-$(CONFIG_MACH_KZM9D_REFERENCE) += board-kzm9d-reference.o
obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o
obj-$(CONFIG_MACH_KZM9G_REFERENCE) += board-kzm9g-reference.o
......
......@@ -7,6 +7,7 @@ loadaddr-$(CONFIG_MACH_ARMADILLO800EVA_REFERENCE) += 0x40008000
loadaddr-$(CONFIG_MACH_BOCKW) += 0x60008000
loadaddr-$(CONFIG_MACH_KOTA2) += 0x41008000
loadaddr-$(CONFIG_MACH_KZM9D) += 0x40008000
loadaddr-$(CONFIG_MACH_KZM9D_REFERENCE) += 0x40008000
loadaddr-$(CONFIG_MACH_KZM9G) += 0x41008000
loadaddr-$(CONFIG_MACH_KZM9G_REFERENCE) += 0x41008000
loadaddr-$(CONFIG_MACH_LAGER) += 0x40008000
......
......@@ -20,8 +20,11 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irqchip.h>
#include <linux/kernel.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mmcif.h>
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/pinctrl/machine.h>
#include <linux/platform_device.h>
#include <linux/regulator/fixed.h>
......@@ -55,6 +58,53 @@ static const struct smsc911x_platform_config lan9220_data = {
.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
};
/*
* On APE6EVM power is supplied to MMCIF by a tps80032 regulator. For now we
* model a VDD supply to MMCIF, using a fixed 3.3V regulator. Also use the
* static power supply for SDHI0 and SDHI1, whereas SDHI0's VccQ is also
* supplied by the same tps80032 regulator and thus can also be adjusted
* dynamically.
*/
static struct regulator_consumer_supply fixed3v3_power_consumers[] =
{
REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"),
REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
};
/* MMCIF */
static struct sh_mmcif_plat_data mmcif0_pdata = {
.caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
};
static struct resource mmcif0_resources[] = {
DEFINE_RES_MEM_NAMED(0xee200000, 0x100, "MMCIF0"),
DEFINE_RES_IRQ(gic_spi(169)),
};
/* SDHI0 */
static struct sh_mobile_sdhi_info sdhi0_pdata = {
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE,
.tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
};
static struct resource sdhi0_resources[] = {
DEFINE_RES_MEM_NAMED(0xee100000, 0x100, "SDHI0"),
DEFINE_RES_IRQ(gic_spi(165)),
};
/* SDHI1 */
static struct sh_mobile_sdhi_info sdhi1_pdata = {
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE,
.tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
MMC_CAP_NEEDS_POLL,
};
static struct resource sdhi1_resources[] = {
DEFINE_RES_MEM_NAMED(0xee120000, 0x100, "SDHI1"),
DEFINE_RES_IRQ(gic_spi(166)),
};
static const struct pinctrl_map ape6evm_pinctrl_map[] = {
/* SCIFA0 console */
PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a73a4",
......@@ -62,6 +112,23 @@ static const struct pinctrl_map ape6evm_pinctrl_map[] = {
/* SMSC */
PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a73a4",
"irqc_irq40", "irqc"),
/* MMCIF0 */
PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a73a4",
"mmc0_data8", "mmc0"),
PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a73a4",
"mmc0_ctrl", "mmc0"),
/* SDHI0: uSD: no WP */
PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a73a4",
"sdhi0_data4", "sdhi0"),
PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a73a4",
"sdhi0_ctrl", "sdhi0"),
PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a73a4",
"sdhi0_cd", "sdhi0"),
/* SDHI1 */
PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a73a4",
"sdhi1_data4", "sdhi1"),
PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a73a4",
"sdhi1_ctrl", "sdhi1"),
};
static void __init ape6evm_add_standard_devices(void)
......@@ -94,6 +161,17 @@ static void __init ape6evm_add_standard_devices(void)
platform_device_register_resndata(&platform_bus, "smsc911x", -1,
lan9220_res, ARRAY_SIZE(lan9220_res),
&lan9220_data, sizeof(lan9220_data));
regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers,
ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
platform_device_register_resndata(&platform_bus, "sh_mmcif", 0,
mmcif0_resources, ARRAY_SIZE(mmcif0_resources),
&mmcif0_pdata, sizeof(mmcif0_pdata));
platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_pdata, sizeof(sdhi0_pdata));
platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 1,
sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
&sdhi1_pdata, sizeof(sdhi1_pdata));
}
static const char *ape6evm_boards_compat_dt[] __initdata = {
......@@ -102,7 +180,7 @@ static const char *ape6evm_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(APE6EVM_DT, "ape6evm")
.init_irq = irqchip_init,
.init_early = r8a73a4_init_delay,
.init_time = shmobile_timer_init,
.init_machine = ape6evm_add_standard_devices,
.dt_compat = ape6evm_boards_compat_dt,
......
......@@ -724,15 +724,6 @@ static struct platform_device vcc_sdhi1 = {
};
/* SDHI0 */
/*
* FIXME
*
* It use polling mode here, since
* CD (= Card Detect) pin is not connected to SDHI0_CD.
* We can use IRQ31 as card detect irq,
* but it needs chattering removal operation
*/
#define IRQ31 irq_pin(31)
static struct sh_mobile_sdhi_info sdhi0_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
......@@ -833,6 +824,8 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = {
.caps = MMC_CAP_4_BIT_DATA |
MMC_CAP_8_BIT_DATA |
MMC_CAP_NONREMOVABLE,
.slave_id_tx = SHDMA_SLAVE_MMCIF_TX,
.slave_id_rx = SHDMA_SLAVE_MMCIF_RX,
};
static struct resource sh_mmcif_resources[] = {
......
/*
* kzm9d board support - Reference DT implementation
*
* Copyright (C) 2013 Renesas Solutions Corp.
* Copyright (C) 2013 Magnus Damm
*
* 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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/init.h>
#include <linux/of_platform.h>
#include <mach/emev2.h>
#include <mach/common.h>
#include <asm/mach/arch.h>
static void __init kzm9d_add_standard_devices(void)
{
emev2_clock_init();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
static const char *kzm9d_boards_compat_dt[] __initdata = {
"renesas,kzm9d-reference",
NULL,
};
DT_MACHINE_START(KZM9D_DT, "kzm9d")
.smp = smp_ops(emev2_smp_ops),
.map_io = emev2_map_io,
.init_early = emev2_init_delay,
.init_machine = kzm9d_add_standard_devices,
.init_late = shmobile_init_late,
.dt_compat = kzm9d_boards_compat_dt,
MACHINE_END
......@@ -85,9 +85,7 @@ static const char *kzm9d_boards_compat_dt[] __initdata = {
DT_MACHINE_START(KZM9D_DT, "kzm9d")
.smp = smp_ops(emev2_smp_ops),
.map_io = emev2_map_io,
.init_early = emev2_add_early_devices,
.nr_irqs = NR_IRQS_LEGACY,
.init_irq = emev2_init_irq,
.init_early = emev2_init_delay,
.init_machine = kzm9d_add_standard_devices,
.init_late = shmobile_init_late,
.dt_compat = kzm9d_boards_compat_dt,
......
......@@ -24,7 +24,6 @@
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/input.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/machine.h>
......@@ -99,7 +98,6 @@ DT_MACHINE_START(KZM9G_DT, "kzm9g-reference")
.map_io = sh73a0_map_io,
.init_early = sh73a0_init_delay,
.nr_irqs = NR_IRQS_LEGACY,
.init_irq = irqchip_init,
.init_machine = kzm_init,
.init_time = shmobile_timer_init,
.dt_compat = kzm9g_boards_compat_dt,
......
......@@ -22,13 +22,17 @@
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/irqchip.h>
#include <linux/kernel.h>
#include <linux/leds.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mmcif.h>
#include <linux/pinctrl/machine.h>
#include <linux/platform_data/gpio-rcar.h>
#include <linux/platform_device.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <mach/common.h>
#include <mach/irqs.h>
#include <mach/r8a7790.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
......@@ -71,6 +75,22 @@ static __initdata struct gpio_keys_platform_data lager_keys_pdata = {
.nbuttons = ARRAY_SIZE(gpio_buttons),
};
/* Fixed 3.3V regulator to be used by MMCIF */
static struct regulator_consumer_supply fixed3v3_power_consumers[] =
{
REGULATOR_SUPPLY("vmmc", "sh_mmcif.1"),
};
/* MMCIF */
static struct sh_mmcif_plat_data mmcif1_pdata = {
.caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
};
static struct resource mmcif1_resources[] = {
DEFINE_RES_MEM_NAMED(0xee220000, 0x80, "MMCIF1"),
DEFINE_RES_IRQ(gic_spi(170)),
};
static const struct pinctrl_map lager_pinctrl_map[] = {
/* SCIF0 (CN19: DEBUG SERIAL0) */
PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.6", "pfc-r8a7790",
......@@ -78,6 +98,11 @@ static const struct pinctrl_map lager_pinctrl_map[] = {
/* SCIF1 (CN20: DEBUG SERIAL1) */
PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.7", "pfc-r8a7790",
"scif1_data", "scif1"),
/* MMCIF1 */
PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.1", "pfc-r8a7790",
"mmc1_data8", "mmc1"),
PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.1", "pfc-r8a7790",
"mmc1_ctrl", "mmc1"),
};
static void __init lager_add_standard_devices(void)
......@@ -95,6 +120,11 @@ static void __init lager_add_standard_devices(void)
platform_device_register_data(&platform_bus, "gpio-keys", -1,
&lager_keys_pdata,
sizeof(lager_keys_pdata));
regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
platform_device_register_resndata(&platform_bus, "sh_mmcif", 1,
mmcif1_resources, ARRAY_SIZE(mmcif1_resources),
&mmcif1_pdata, sizeof(mmcif1_pdata));
}
static const char *lager_boards_compat_dt[] __initdata = {
......@@ -103,7 +133,7 @@ static const char *lager_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(LAGER_DT, "lager")
.init_irq = irqchip_init,
.init_early = r8a7790_init_delay,
.init_time = r8a7790_timer_init,
.init_machine = lager_add_standard_devices,
.dt_compat = lager_boards_compat_dt,
......
......@@ -40,7 +40,6 @@
#define USIB2SCLKDIV 0x65c
#define USIB3SCLKDIV 0x660
#define STI_CLKSEL 0x688
#define SMU_GENERAL_REG0 0x7c0
/* not pretty, but hey */
static void __iomem *smu_base;
......@@ -51,11 +50,6 @@ static void emev2_smu_write(unsigned long value, int offs)
iowrite32(value, smu_base + offs);
}
void emev2_set_boot_vector(unsigned long value)
{
emev2_smu_write(value, SMU_GENERAL_REG0);
}
static struct clk_mapping smu_mapping = {
.phys = EMEV2_SMU_BASE,
.len = PAGE_SIZE,
......@@ -205,23 +199,11 @@ static struct clk_lookup lookups[] = {
void __init emev2_clock_init(void)
{
int k, ret = 0;
static int is_setup;
/* yuck, this is ugly as hell, but the non-smp case of clocks
* code is now designed to rely on ioremap() instead of static
* entity maps. in the case of smp we need access to the SMU
* register earlier than ioremap() is actually working without
* any static maps. to enable SMP in ugly but with dynamic
* mappings we have to call emev2_clock_init() from different
* places depending on UP and SMP...
*/
if (is_setup++)
return;
smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
BUG_ON(!smu_base);
/* setup STI timer to run on 37.768 kHz and deassert reset */
/* setup STI timer to run on 32.768 kHz and deassert reset */
emev2_smu_write(0, STI_CLKSEL);
emev2_smu_write(1, STI_RSTCTRL);
......
......@@ -30,10 +30,12 @@
#define SMSTPCR2 0xe6150138
#define SMSTPCR3 0xe615013c
#define SMSTPCR4 0xe6150140
#define SMSTPCR5 0xe6150144
#define FRQCRA 0xE6150000
#define FRQCRB 0xE6150004
#define FRQCRC 0xE61500E0
#define VCLKCR1 0xE6150008
#define VCLKCR2 0xE615000C
#define VCLKCR3 0xE615001C
......@@ -52,6 +54,7 @@
#define HSICKCR 0xE615026C
#define M4CKCR 0xE6150098
#define PLLECR 0xE61500D0
#define PLL0CR 0xE61500D8
#define PLL1CR 0xE6150028
#define PLL2CR 0xE615002C
#define PLL2SCR 0xE61501F4
......@@ -177,6 +180,7 @@ static struct sh_clk_ops pll_clk_ops = {
.mapping = &cpg_mapping, \
}
PLL_CLOCK(pll0_clk, &main_clk, pll_parent_main, 1, 20, PLL0CR, 0);
PLL_CLOCK(pll1_clk, &main_clk, pll_parent_main, 1, 7, PLL1CR, 1);
PLL_CLOCK(pll2_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2CR, 2);
PLL_CLOCK(pll2s_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2SCR, 4);
......@@ -184,6 +188,157 @@ PLL_CLOCK(pll2h_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2HCR, 5);
SH_FIXED_RATIO_CLK(pll1_div2_clk, pll1_clk, div2);
static atomic_t frqcr_lock;
/* Several clocks need to access FRQCRB, have to lock */
static bool frqcr_kick_check(struct clk *clk)
{
return !(ioread32(CPG_MAP(FRQCRB)) & BIT(31));
}
static int frqcr_kick_do(struct clk *clk)
{
int i;
/* set KICK bit in FRQCRB to update hardware setting, check success */
iowrite32(ioread32(CPG_MAP(FRQCRB)) | BIT(31), CPG_MAP(FRQCRB));
for (i = 1000; i; i--)
if (ioread32(CPG_MAP(FRQCRB)) & BIT(31))
cpu_relax();
else
return 0;
return -ETIMEDOUT;
}
static int zclk_set_rate(struct clk *clk, unsigned long rate)
{
void __iomem *frqcrc;
int ret;
unsigned long step, p_rate;
u32 val;
if (!clk->parent || !__clk_get(clk->parent))
return -ENODEV;
if (!atomic_inc_and_test(&frqcr_lock) || !frqcr_kick_check(clk)) {
ret = -EBUSY;
goto done;
}
/*
* Users are supposed to first call clk_set_rate() only with
* clk_round_rate() results. So, we don't fix wrong rates here, but
* guard against them anyway
*/
p_rate = clk_get_rate(clk->parent);
if (rate == p_rate) {
val = 0;
} else {
step = DIV_ROUND_CLOSEST(p_rate, 32);
if (rate > p_rate || rate < step) {
ret = -EINVAL;
goto done;
}
val = 32 - rate / step;
}
frqcrc = clk->mapped_reg + (FRQCRC - (u32)clk->enable_reg);
iowrite32((ioread32(frqcrc) & ~(clk->div_mask << clk->enable_bit)) |
(val << clk->enable_bit), frqcrc);
ret = frqcr_kick_do(clk);
done:
atomic_dec(&frqcr_lock);
__clk_put(clk->parent);
return ret;
}
static long zclk_round_rate(struct clk *clk, unsigned long rate)
{
/*
* theoretical rate = parent rate * multiplier / 32,
* where 1 <= multiplier <= 32. Therefore we should do
* multiplier = rate * 32 / parent rate
* rounded rate = parent rate * multiplier / 32.
* However, multiplication before division won't fit in 32 bits, so
* we sacrifice some precision by first dividing and then multiplying.
* To find the nearest divisor we calculate both and pick up the best
* one. This avoids 64-bit arithmetics.
*/
unsigned long step, mul_min, mul_max, rate_min, rate_max;
rate_max = clk_get_rate(clk->parent);
/* output freq <= parent */
if (rate >= rate_max)
return rate_max;
step = DIV_ROUND_CLOSEST(rate_max, 32);
/* output freq >= parent / 32 */
if (step >= rate)
return step;
mul_min = rate / step;
mul_max = DIV_ROUND_UP(rate, step);
rate_min = step * mul_min;
if (mul_max == mul_min)
return rate_min;
rate_max = step * mul_max;
if (rate_max - rate < rate - rate_min)
return rate_max;
return rate_min;
}
static unsigned long zclk_recalc(struct clk *clk)
{
void __iomem *frqcrc = FRQCRC - (u32)clk->enable_reg + clk->mapped_reg;
unsigned int max = clk->div_mask + 1;
unsigned long val = ((ioread32(frqcrc) >> clk->enable_bit) &
clk->div_mask);
return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), max) *
(max - val);
}
static struct sh_clk_ops zclk_ops = {
.recalc = zclk_recalc,
.set_rate = zclk_set_rate,
.round_rate = zclk_round_rate,
};
static struct clk z_clk = {
.parent = &pll0_clk,
.div_mask = 0x1f,
.enable_bit = 8,
/* We'll need to access FRQCRB and FRQCRC */
.enable_reg = (void __iomem *)FRQCRB,
.ops = &zclk_ops,
};
/*
* It seems only 1/2 divider is usable in manual mode. 1/2 / 2/3
* switching is only available in auto-DVFS mode
*/
SH_FIXED_RATIO_CLK(pll0_div2_clk, pll0_clk, div2);
static struct clk z2_clk = {
.parent = &pll0_div2_clk,
.div_mask = 0x1f,
.enable_bit = 0,
/* We'll need to access FRQCRB and FRQCRC */
.enable_reg = (void __iomem *)FRQCRB,
.ops = &zclk_ops,
};
static struct clk *main_clks[] = {
&extalr_clk,
&extal1_clk,
......@@ -195,22 +350,23 @@ static struct clk *main_clks[] = {
&main_div2_clk,
&fsiack_clk,
&fsibck_clk,
&pll0_clk,
&pll1_clk,
&pll1_div2_clk,
&pll2_clk,
&pll2s_clk,
&pll2h_clk,
&z_clk,
&pll0_div2_clk,
&z2_clk,
};
/* DIV4 */
static void div4_kick(struct clk *clk)
{
unsigned long value;
/* set KICK bit in FRQCRB to update hardware setting */
value = ioread32(CPG_MAP(FRQCRB));
value |= (1 << 31);
iowrite32(value, CPG_MAP(FRQCRB));
if (!WARN(!atomic_inc_and_test(&frqcr_lock), "FRQCR* lock broken!\n"))
frqcr_kick_do(clk);
atomic_dec(&frqcr_lock);
}
static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 24, 0, 36, 48, 10};
......@@ -349,8 +505,10 @@ static struct clk div6_clks[DIV6_NR] = {
/* MSTP */
enum {
MSTP217, MSTP216, MSTP207, MSTP206, MSTP204, MSTP203,
MSTP315, MSTP314, MSTP313, MSTP312, MSTP305,
MSTP522,
MSTP329, MSTP323, MSTP318, MSTP317, MSTP316,
MSTP315, MSTP314, MSTP313, MSTP312, MSTP305, MSTP300,
MSTP411, MSTP410, MSTP409,
MSTP522, MSTP515,
MSTP_NR
};
......@@ -361,12 +519,22 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_MP], SMSTPCR2, 7, 0), /* SCIFB1 */
[MSTP216] = SH_CLK_MSTP32(&div6_clks[DIV6_MP], SMSTPCR2, 16, 0), /* SCIFB2 */
[MSTP217] = SH_CLK_MSTP32(&div6_clks[DIV6_MP], SMSTPCR2, 17, 0), /* SCIFB3 */
[MSTP300] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 0, 0), /* IIC2 */
[MSTP305] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC1],SMSTPCR3, 5, 0), /* MMCIF1 */
[MSTP312] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI2],SMSTPCR3, 12, 0), /* SDHI2 */
[MSTP313] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI1],SMSTPCR3, 13, 0), /* SDHI1 */
[MSTP314] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI0],SMSTPCR3, 14, 0), /* SDHI0 */
[MSTP315] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC0],SMSTPCR3, 15, 0), /* MMCIF0 */
[MSTP316] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 16, 0), /* IIC6 */
[MSTP317] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 17, 0), /* IIC7 */
[MSTP318] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 18, 0), /* IIC0 */
[MSTP323] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */
[MSTP329] = SH_CLK_MSTP32(&extalr_clk, SMSTPCR3, 29, 0), /* CMT10 */
[MSTP409] = SH_CLK_MSTP32(&main_div2_clk, SMSTPCR4, 9, 0), /* IIC5 */
[MSTP410] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */
[MSTP411] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */
[MSTP522] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR5, 22, 0), /* Thermal */
[MSTP515] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR5, 15, 0), /* IIC8 */
};
static struct clk_lookup lookups[] = {
......@@ -386,6 +554,9 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("pll2s", &pll2s_clk),
CLKDEV_CON_ID("pll2h", &pll2h_clk),
/* CPU clock */
CLKDEV_DEV_ID("cpufreq-cpu0", &z_clk),
/* DIV6 */
CLKDEV_CON_ID("zb", &div6_clks[DIV6_ZB]),
CLKDEV_CON_ID("vck1", &div6_clks[DIV6_VCK1]),
......@@ -408,6 +579,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]),
CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP217]),
CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
CLKDEV_DEV_ID("e6520000.i2c", &mstp_clks[MSTP300]),
CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
CLKDEV_DEV_ID("ee220000.mmcif", &mstp_clks[MSTP305]),
CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]),
......@@ -418,6 +590,15 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]),
CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]),
CLKDEV_DEV_ID("ee200000.mmcif", &mstp_clks[MSTP315]),
CLKDEV_DEV_ID("e6550000.i2c", &mstp_clks[MSTP316]),
CLKDEV_DEV_ID("e6560000.i2c", &mstp_clks[MSTP317]),
CLKDEV_DEV_ID("e6500000.i2c", &mstp_clks[MSTP318]),
CLKDEV_DEV_ID("e6510000.i2c", &mstp_clks[MSTP323]),
CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]),
CLKDEV_DEV_ID("e60b0000.i2c", &mstp_clks[MSTP409]),
CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP410]),
CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP411]),
CLKDEV_DEV_ID("e6570000.i2c", &mstp_clks[MSTP515]),
/* for DT */
CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]),
......@@ -429,6 +610,8 @@ void __init r8a73a4_clock_init(void)
int k, ret = 0;
u32 ckscr;
atomic_set(&frqcr_lock, -1);
reg = ioremap_nocache(CKSCR, PAGE_SIZE);
BUG_ON(!reg);
ckscr = ioread32(reg);
......
......@@ -24,6 +24,7 @@
#include <linux/clkdev.h>
#include <mach/clock.h>
#include <mach/common.h>
#include <mach/r8a7790.h>
/*
* MD EXTAL PLL0 PLL1 PLL3
......@@ -42,16 +43,15 @@
* see "p1 / 2" on R8A7790_CLOCK_ROOT() below
*/
#define MD(nr) (1 << nr)
#define CPG_BASE 0xe6150000
#define CPG_LEN 0x1000
#define SMSTPCR1 0xe6150134
#define SMSTPCR2 0xe6150138
#define SMSTPCR3 0xe615013c
#define SMSTPCR5 0xe6150144
#define SMSTPCR7 0xe615014c
#define MODEMR 0xE6160060
#define SDCKCR 0xE6150074
#define SD2CKCR 0xE6150078
#define SD3CKCR 0xE615007C
......@@ -182,14 +182,19 @@ static struct clk div6_clks[DIV6_NR] = {
enum {
MSTP721, MSTP720,
MSTP717, MSTP716,
MSTP522,
MSTP315, MSTP314, MSTP313, MSTP312, MSTP311, MSTP305, MSTP304,
MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202,
MSTP124,
MSTP_NR
};
static struct clk mstp_clks[MSTP_NR] = {
[MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */
[MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
[MSTP717] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 17, 0), /* HSCIF0 */
[MSTP716] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 16, 0), /* HSCIF1 */
[MSTP522] = SH_CLK_MSTP32(&extal_clk, SMSTPCR5, 22, 0), /* Thermal */
[MSTP315] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC0], SMSTPCR3, 15, 0), /* MMC0 */
[MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_SD0], SMSTPCR3, 14, 0), /* SDHI0 */
[MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_SD1], SMSTPCR3, 13, 0), /* SDHI1 */
......@@ -203,8 +208,7 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP204] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 4, 0), /* SCIFA0 */
[MSTP203] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 3, 0), /* SCIFA1 */
[MSTP202] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 2, 0), /* SCIFA2 */
[MSTP717] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 17, 0), /* HSCIF0 */
[MSTP716] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 16, 0), /* HSCIF1 */
[MSTP124] = SH_CLK_MSTP32(&rclk_clk, SMSTPCR1, 24, 0), /* CMT0 */
};
static struct clk_lookup lookups[] = {
......@@ -254,6 +258,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]),
CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP717]),
CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP716]),
CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
CLKDEV_DEV_ID("ee200000.mmcif", &mstp_clks[MSTP315]),
CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]),
CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]),
......@@ -266,6 +271,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP311]),
CLKDEV_DEV_ID("ee220000.mmcif", &mstp_clks[MSTP305]),
CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]),
};
#define R8A7790_CLOCK_ROOT(e, m, p0, p1, p30, p31) \
......@@ -280,14 +286,9 @@ static struct clk_lookup lookups[] = {
void __init r8a7790_clock_init(void)
{
void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
u32 mode;
u32 mode = r8a7790_read_mode_pins();
int k, ret = 0;
BUG_ON(!modemr);
mode = ioread32(modemr);
iounmap(modemr);
switch (mode & (MD(14) | MD(13))) {
case 0:
R8A7790_CLOCK_ROOT(15, &extal_clk, 172, 208, 106, 88);
......
......@@ -2,11 +2,9 @@
#define __ASM_EMEV2_H__
extern void emev2_map_io(void);
extern void emev2_init_irq(void);
extern void emev2_add_early_devices(void);
extern void emev2_init_delay(void);
extern void emev2_add_standard_devices(void);
extern void emev2_clock_init(void);
extern void emev2_set_boot_vector(unsigned long value);
#define EMEV2_GPIO_BASE 200
#define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
......
......@@ -4,5 +4,6 @@
void r8a73a4_add_standard_devices(void);
void r8a73a4_clock_init(void);
void r8a73a4_pinmux_init(void);
void r8a73a4_init_delay(void);
#endif /* __ASM_R8A73A4_H__ */
......@@ -42,6 +42,8 @@ enum {
SHDMA_SLAVE_FSIB_TX,
SHDMA_SLAVE_USBHS_TX,
SHDMA_SLAVE_USBHS_RX,
SHDMA_SLAVE_MMCIF_TX,
SHDMA_SLAVE_MMCIF_RX,
};
extern void r8a7740_meram_workaround(void);
......
......@@ -33,7 +33,6 @@ extern void r8a7778_add_mmc_device(struct sh_mmcif_plat_data *info);
extern void r8a7778_init_late(void);
extern void r8a7778_init_delay(void);
extern void r8a7778_init_irq(void);
extern void r8a7778_init_irq_dt(void);
extern void r8a7778_clock_init(void);
extern void r8a7778_init_irq_extpin(int irlm);
......
......@@ -4,6 +4,10 @@
void r8a7790_add_standard_devices(void);
void r8a7790_clock_init(void);
void r8a7790_pinmux_init(void);
void r8a7790_init_delay(void);
void r8a7790_timer_init(void);
#define MD(nr) BIT(nr)
u32 r8a7790_read_mode_pins(void);
#endif /* __ASM_R8A7790_H__ */
This diff is collapsed.
......@@ -18,11 +18,11 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/kernel.h>
#include <linux/of_platform.h>
#include <linux/platform_data/irq-renesas-irqc.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
#include <mach/common.h>
#include <mach/irqs.h>
#include <mach/r8a73a4.h>
......@@ -169,6 +169,25 @@ static const struct resource thermal0_resources[] = {
thermal0_resources, \
ARRAY_SIZE(thermal0_resources))
static struct sh_timer_config cmt10_platform_data = {
.name = "CMT10",
.timer_bit = 0,
.clockevent_rating = 80,
};
static struct resource cmt10_resources[] = {
DEFINE_RES_MEM(0xe6130010, 0x0c),
DEFINE_RES_MEM(0xe6130000, 0x04),
DEFINE_RES_IRQ(gic_spi(120)), /* CMT1_0 */
};
#define r8a7790_register_cmt(idx) \
platform_device_register_resndata(&platform_bus, "sh_cmt", \
idx, cmt##idx##_resources, \
ARRAY_SIZE(cmt##idx##_resources), \
&cmt##idx##_platform_data, \
sizeof(struct sh_timer_config))
void __init r8a73a4_add_standard_devices(void)
{
r8a73a4_register_scif(SCIFA0);
......@@ -180,11 +199,20 @@ void __init r8a73a4_add_standard_devices(void)
r8a73a4_register_irqc(0);
r8a73a4_register_irqc(1);
r8a73a4_register_thermal();
r8a7790_register_cmt(10);
}
void __init r8a73a4_init_delay(void)
{
#ifndef CONFIG_ARM_ARCH_TIMER
shmobile_setup_delay(1500, 2, 4); /* Cortex-A15 @ 1500MHz */
#endif
}
#ifdef CONFIG_USE_OF
void __init r8a73a4_add_standard_devices_dt(void)
{
platform_device_register_simple("cpufreq-cpu0", -1, NULL, 0);
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
......@@ -194,7 +222,7 @@ static const char *r8a73a4_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)")
.init_irq = irqchip_init,
.init_early = r8a73a4_init_delay,
.init_machine = r8a73a4_add_standard_devices_dt,
.init_time = shmobile_timer_init,
.dt_compat = r8a73a4_boards_compat_dt,
......
......@@ -588,6 +588,16 @@ static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = {
.addr = 0xfe1f0064,
.chcr = CHCR_TX(XMIT_SZ_32BIT),
.mid_rid = 0xb5,
}, {
.slave_id = SHDMA_SLAVE_MMCIF_TX,
.addr = 0xe6bd0034,
.chcr = CHCR_TX(XMIT_SZ_32BIT),
.mid_rid = 0xd1,
}, {
.slave_id = SHDMA_SLAVE_MMCIF_RX,
.addr = 0xe6bd0034,
.chcr = CHCR_RX(XMIT_SZ_32BIT),
.mid_rid = 0xd2,
},
};
......@@ -986,16 +996,22 @@ void __init r8a7740_add_early_devices(void)
#ifdef CONFIG_USE_OF
static const struct of_dev_auxdata r8a7740_auxdata_lookup[] __initconst = {
{ }
};
void __init r8a7740_add_early_devices_dt(void)
{
shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */
early_platform_add_devices(r8a7740_early_devices,
ARRAY_SIZE(r8a7740_early_devices));
/* setup early console here as well */
shmobile_setup_console();
}
void __init r8a7740_add_standard_devices_dt(void)
{
platform_add_devices(r8a7740_devices_dt,
ARRAY_SIZE(r8a7740_devices_dt));
of_platform_populate(NULL, of_default_bus_match_table,
r8a7740_auxdata_lookup, NULL);
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
void __init r8a7740_init_delay(void)
......
......@@ -53,7 +53,7 @@
.irqs = SCIx_IRQ_MUXED(irq), \
}
static struct plat_sci_port scif_platform_data[] = {
static struct plat_sci_port scif_platform_data[] __initdata = {
SCIF_INFO(0xffe40000, gic_iid(0x66)),
SCIF_INFO(0xffe41000, gic_iid(0x67)),
SCIF_INFO(0xffe42000, gic_iid(0x68)),
......@@ -63,24 +63,24 @@ static struct plat_sci_port scif_platform_data[] = {
};
/* TMU */
static struct resource sh_tmu0_resources[] = {
static struct resource sh_tmu0_resources[] __initdata = {
DEFINE_RES_MEM(0xffd80008, 12),
DEFINE_RES_IRQ(gic_iid(0x40)),
};
static struct sh_timer_config sh_tmu0_platform_data = {
static struct sh_timer_config sh_tmu0_platform_data __initdata = {
.name = "TMU00",
.channel_offset = 0x4,
.timer_bit = 0,
.clockevent_rating = 200,
};
static struct resource sh_tmu1_resources[] = {
static struct resource sh_tmu1_resources[] __initdata = {
DEFINE_RES_MEM(0xffd80014, 12),
DEFINE_RES_IRQ(gic_iid(0x41)),
};
static struct sh_timer_config sh_tmu1_platform_data = {
static struct sh_timer_config sh_tmu1_platform_data __initdata = {
.name = "TMU01",
.channel_offset = 0x10,
.timer_bit = 1,
......@@ -189,7 +189,7 @@ USB_PLATFORM_INFO(ehci);
USB_PLATFORM_INFO(ohci);
/* Ether */
static struct resource ether_resources[] = {
static struct resource ether_resources[] __initdata = {
DEFINE_RES_MEM(0xfde00000, 0x400),
DEFINE_RES_IRQ(gic_iid(0x89)),
};
......@@ -203,17 +203,17 @@ void __init r8a7778_add_ether_device(struct sh_eth_plat_data *pdata)
}
/* PFC/GPIO */
static struct resource pfc_resources[] = {
static struct resource pfc_resources[] __initdata = {
DEFINE_RES_MEM(0xfffc0000, 0x118),
};
#define R8A7778_GPIO(idx) \
static struct resource r8a7778_gpio##idx##_resources[] = { \
static struct resource r8a7778_gpio##idx##_resources[] __initdata = { \
DEFINE_RES_MEM(0xffc40000 + 0x1000 * (idx), 0x30), \
DEFINE_RES_IRQ(gic_iid(0x87)), \
}; \
\
static struct gpio_rcar_config r8a7778_gpio##idx##_platform_data = { \
static struct gpio_rcar_config r8a7778_gpio##idx##_platform_data __initdata = { \
.gpio_base = 32 * (idx), \
.irq_base = GPIO_IRQ_BASE(idx), \
.number_of_pins = 32, \
......@@ -249,7 +249,7 @@ void __init r8a7778_pinmux_init(void)
};
/* SDHI */
static struct resource sdhi_resources[] = {
static struct resource sdhi_resources[] __initdata = {
/* SDHI0 */
DEFINE_RES_MEM(0xFFE4C000, 0x100),
DEFINE_RES_IRQ(gic_iid(0x77)),
......@@ -365,12 +365,12 @@ void __init r8a7778_init_late(void)
platform_device_register_full(&ohci_info);
}
static struct renesas_intc_irqpin_config irqpin_platform_data = {
static struct renesas_intc_irqpin_config irqpin_platform_data __initdata = {
.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
.sense_bitfield_width = 2,
};
static struct resource irqpin_resources[] = {
static struct resource irqpin_resources[] __initdata = {
DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
......@@ -408,17 +408,25 @@ void __init r8a7778_init_irq_extpin(int irlm)
&irqpin_platform_data, sizeof(irqpin_platform_data));
}
void __init r8a7778_init_delay(void)
{
shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */
}
#ifdef CONFIG_USE_OF
#define INT2SMSKCR0 0x82288 /* 0xfe782288 */
#define INT2SMSKCR1 0x8228c /* 0xfe78228c */
#define INT2NTSR0 0x00018 /* 0xfe700018 */
#define INT2NTSR1 0x0002c /* 0xfe70002c */
static void __init r8a7778_init_irq_common(void)
void __init r8a7778_init_irq_dt(void)
{
void __iomem *base = ioremap_nocache(0xfe700000, 0x00100000);
BUG_ON(!base);
irqchip_init();
/* route all interrupts to ARM */
__raw_writel(0x73ffffff, base + INT2NTSR0);
__raw_writel(0xffffffff, base + INT2NTSR1);
......@@ -430,43 +438,6 @@ static void __init r8a7778_init_irq_common(void)
iounmap(base);
}
void __init r8a7778_init_irq(void)
{
void __iomem *gic_dist_base;
void __iomem *gic_cpu_base;
gic_dist_base = ioremap_nocache(0xfe438000, PAGE_SIZE);
gic_cpu_base = ioremap_nocache(0xfe430000, PAGE_SIZE);
BUG_ON(!gic_dist_base || !gic_cpu_base);
/* use GIC to handle interrupts */
gic_init(0, 29, gic_dist_base, gic_cpu_base);
r8a7778_init_irq_common();
}
void __init r8a7778_init_delay(void)
{
shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */
}
#ifdef CONFIG_USE_OF
void __init r8a7778_init_irq_dt(void)
{
irqchip_init();
r8a7778_init_irq_common();
}
static const struct of_dev_auxdata r8a7778_auxdata_lookup[] __initconst = {
{},
};
void __init r8a7778_add_standard_devices_dt(void)
{
of_platform_populate(NULL, of_default_bus_match_table,
r8a7778_auxdata_lookup, NULL);
}
static const char *r8a7778_compat_dt[] __initdata = {
"renesas,r8a7778",
NULL,
......@@ -475,7 +446,6 @@ static const char *r8a7778_compat_dt[] __initdata = {
DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)")
.init_early = r8a7778_init_delay,
.init_irq = r8a7778_init_irq_dt,
.init_machine = r8a7778_add_standard_devices_dt,
.init_time = shmobile_timer_init,
.dt_compat = r8a7778_compat_dt,
.init_late = r8a7778_init_late,
......
......@@ -665,10 +665,6 @@ void __init r8a7779_init_delay(void)
shmobile_setup_delay(1000, 2, 4); /* Cortex-A9 @ 1000MHz */
}
static const struct of_dev_auxdata r8a7779_auxdata_lookup[] __initconst = {
{},
};
void __init r8a7779_add_standard_devices_dt(void)
{
/* clocks are setup late during boot in the case of DT */
......@@ -676,8 +672,7 @@ void __init r8a7779_add_standard_devices_dt(void)
platform_add_devices(r8a7779_devices_dt,
ARRAY_SIZE(r8a7779_devices_dt));
of_platform_populate(NULL, of_default_bus_match_table,
r8a7779_auxdata_lookup, NULL);
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
static const char *r8a7779_compat_dt[] __initdata = {
......
......@@ -19,12 +19,12 @@
*/
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/kernel.h>
#include <linux/of_platform.h>
#include <linux/serial_sci.h>
#include <linux/platform_data/gpio-rcar.h>
#include <linux/platform_data/irq-renesas-irqc.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
#include <mach/common.h>
#include <mach/irqs.h>
#include <mach/r8a7790.h>
......@@ -149,6 +149,36 @@ static struct resource irqc0_resources[] __initdata = {
&irqc##idx##_data, \
sizeof(struct renesas_irqc_config))
static struct resource thermal_resources[] __initdata = {
DEFINE_RES_MEM(0xe61f0000, 0x14),
DEFINE_RES_MEM(0xe61f0100, 0x38),
DEFINE_RES_IRQ(gic_spi(69)),
};
#define r8a7790_register_thermal() \
platform_device_register_simple("rcar_thermal", -1, \
thermal_resources, \
ARRAY_SIZE(thermal_resources))
static struct sh_timer_config cmt00_platform_data = {
.name = "CMT00",
.timer_bit = 0,
.clockevent_rating = 80,
};
static struct resource cmt00_resources[] = {
DEFINE_RES_MEM(0xffca0510, 0x0c),
DEFINE_RES_MEM(0xffca0500, 0x04),
DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */
};
#define r8a7790_register_cmt(idx) \
platform_device_register_resndata(&platform_bus, "sh_cmt", \
idx, cmt##idx##_resources, \
ARRAY_SIZE(cmt##idx##_resources), \
&cmt##idx##_platform_data, \
sizeof(struct sh_timer_config))
void __init r8a7790_add_standard_devices(void)
{
r8a7790_register_scif(SCIFA0);
......@@ -162,34 +192,91 @@ void __init r8a7790_add_standard_devices(void)
r8a7790_register_scif(HSCIF0);
r8a7790_register_scif(HSCIF1);
r8a7790_register_irqc(0);
r8a7790_register_thermal();
r8a7790_register_cmt(00);
}
#define MODEMR 0xe6160060
u32 __init r8a7790_read_mode_pins(void)
{
void __iomem *modemr = ioremap_nocache(MODEMR, 4);
u32 mode;
BUG_ON(!modemr);
mode = ioread32(modemr);
iounmap(modemr);
return mode;
}
#define CNTCR 0
#define CNTFID0 0x20
void __init r8a7790_timer_init(void)
{
void __iomem *cntcr;
#ifdef CONFIG_ARM_ARCH_TIMER
u32 mode = r8a7790_read_mode_pins();
void __iomem *base;
int extal_mhz = 0;
u32 freq;
/* At Linux boot time the r8a7790 arch timer comes up
* with the counter disabled. Moreover, it may also report
* a potentially incorrect fixed 13 MHz frequency. To be
* correct these registers need to be updated to use the
* frequency EXTAL / 2 which can be determined by the MD pins.
*/
switch (mode & (MD(14) | MD(13))) {
case 0:
extal_mhz = 15;
break;
case MD(13):
extal_mhz = 20;
break;
case MD(14):
extal_mhz = 26;
break;
case MD(13) | MD(14):
extal_mhz = 30;
break;
}
/* make sure arch timer is started by setting bit 0 of CNTCT */
cntcr = ioremap(0xe6080000, PAGE_SIZE);
iowrite32(1, cntcr);
iounmap(cntcr);
/* The arch timer frequency equals EXTAL / 2 */
freq = extal_mhz * (1000000 / 2);
/* Remap "armgcnt address map" space */
base = ioremap(0xe6080000, PAGE_SIZE);
/* Update registers with correct frequency */
iowrite32(freq, base + CNTFID0);
asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
/* make sure arch timer is started by setting bit 0 of CNTCR */
iowrite32(1, base + CNTCR);
iounmap(base);
#endif /* CONFIG_ARM_ARCH_TIMER */
shmobile_timer_init();
}
#ifdef CONFIG_USE_OF
void __init r8a7790_add_standard_devices_dt(void)
void __init r8a7790_init_delay(void)
{
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
#ifndef CONFIG_ARM_ARCH_TIMER
shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
#endif
}
#ifdef CONFIG_USE_OF
static const char *r8a7790_boards_compat_dt[] __initdata = {
"renesas,r8a7790",
NULL,
};
DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
.init_irq = irqchip_init,
.init_machine = r8a7790_add_standard_devices_dt,
.init_early = r8a7790_init_delay,
.init_time = r8a7790_timer_init,
.dt_compat = r8a7790_boards_compat_dt,
MACHINE_END
......
......@@ -1147,10 +1147,6 @@ void __init sh7372_add_early_devices_dt(void)
shmobile_setup_console();
}
static const struct of_dev_auxdata sh7372_auxdata_lookup[] __initconst = {
{ }
};
void __init sh7372_add_standard_devices_dt(void)
{
/* clocks are setup late during boot in the case of DT */
......@@ -1159,8 +1155,7 @@ void __init sh7372_add_standard_devices_dt(void)
platform_add_devices(sh7372_early_devices,
ARRAY_SIZE(sh7372_early_devices));
of_platform_populate(NULL, of_default_bus_match_table,
sh7372_auxdata_lookup, NULL);
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
static const char *sh7372_boards_compat_dt[] __initdata = {
......
......@@ -22,7 +22,6 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/delay.h>
......@@ -61,29 +60,16 @@ void __init sh73a0_map_io(void)
iotable_init(sh73a0_io_desc, ARRAY_SIZE(sh73a0_io_desc));
}
static struct resource sh73a0_pfc_resources[] = {
[0] = {
.start = 0xe6050000,
.end = 0xe6057fff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 0xe605801c,
.end = 0xe6058027,
.flags = IORESOURCE_MEM,
}
};
static struct platform_device sh73a0_pfc_device = {
.name = "pfc-sh73a0",
.id = -1,
.resource = sh73a0_pfc_resources,
.num_resources = ARRAY_SIZE(sh73a0_pfc_resources),
/* PFC */
static struct resource pfc_resources[] __initdata = {
DEFINE_RES_MEM(0xe6050000, 0x8000),
DEFINE_RES_MEM(0xe605801c, 0x000c),
};
void __init sh73a0_pinmux_init(void)
{
platform_device_register(&sh73a0_pfc_device);
platform_device_register_simple("pfc-sh73a0", -1, pfc_resources,
ARRAY_SIZE(pfc_resources));
}
static struct plat_sci_port scif0_platform_data = {
......@@ -958,10 +944,6 @@ void __init sh73a0_add_early_devices(void)
#ifdef CONFIG_USE_OF
static const struct of_dev_auxdata sh73a0_auxdata_lookup[] __initconst = {
{},
};
void __init sh73a0_add_standard_devices_dt(void)
{
struct platform_device_info devinfo = { .name = "cpufreq-cpu0", .id = -1, };
......@@ -971,8 +953,7 @@ void __init sh73a0_add_standard_devices_dt(void)
platform_add_devices(sh73a0_devices_dt,
ARRAY_SIZE(sh73a0_devices_dt));
of_platform_populate(NULL, of_default_bus_match_table,
sh73a0_auxdata_lookup, NULL);
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
/* Instantiate cpufreq-cpu0 */
platform_device_register_full(&devinfo);
......@@ -988,7 +969,6 @@ DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
.map_io = sh73a0_map_io,
.init_early = sh73a0_init_delay,
.nr_irqs = NR_IRQS_LEGACY,
.init_irq = irqchip_init,
.init_machine = sh73a0_add_standard_devices_dt,
.dt_compat = sh73a0_boards_compat_dt,
MACHINE_END
......
......@@ -29,6 +29,8 @@
#include <asm/smp_scu.h>
#define EMEV2_SCU_BASE 0x1e000000
#define EMEV2_SMU_BASE 0xe0110000
#define SMU_GENERAL_REG0 0x7c0
static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
......@@ -38,10 +40,18 @@ static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
{
void __iomem *smu;
/* setup EMEV2 specific SCU base, enable */
shmobile_scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
scu_enable(shmobile_scu_base);
/* Tell ROM loader about our vector (in headsmp-scu.S, headsmp.S) */
emev2_set_boot_vector(__pa(shmobile_boot_vector));
smu = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
if (smu) {
iowrite32(__pa(shmobile_boot_vector), smu + SMU_GENERAL_REG0);
iounmap(smu);
}
shmobile_boot_fn = virt_to_phys(shmobile_boot_scu);
shmobile_boot_arg = (unsigned long)shmobile_scu_base;
......@@ -49,21 +59,7 @@ static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
}
static void __init emev2_smp_init_cpus(void)
{
unsigned int ncores;
/* setup EMEV2 specific SCU base */
shmobile_scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
emev2_clock_init(); /* need ioremapped SMU */
ncores = shmobile_scu_base ? scu_get_core_count(shmobile_scu_base) : 1;
shmobile_smp_init_cpus(ncores);
}
struct smp_operations emev2_smp_ops __initdata = {
.smp_init_cpus = emev2_smp_init_cpus,
.smp_prepare_cpus = emev2_smp_prepare_cpus,
.smp_boot_secondary = emev2_boot_secondary,
};
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