board-ape6evm.c 8.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * APE6EVM board support
 *
 * 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.
 */

17
#include <linux/gpio.h>
18 19
#include <linux/gpio_keys.h>
#include <linux/input.h>
20 21
#include <linux/interrupt.h>
#include <linux/kernel.h>
22
#include <linux/mfd/tmio.h>
23 24
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mmcif.h>
25
#include <linux/mmc/sh_mobile_sdhi.h>
M
Magnus Damm 已提交
26
#include <linux/pinctrl/machine.h>
27
#include <linux/platform_device.h>
28 29
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
30
#include <linux/sh_clk.h>
31
#include <linux/smsc911x.h>
32

33 34 35
#include <asm/mach-types.h>
#include <asm/mach/arch.h>

M
Magnus Damm 已提交
36
#include "common.h"
37
#include "irqs.h"
38
#include "r8a73a4.h"
39

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
/* LEDS */
static struct gpio_led ape6evm_leds[] = {
	{
		.name		= "gnss-en",
		.gpio		= 28,
		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
	}, {
		.name		= "nfc-nrst",
		.gpio		= 126,
		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
	}, {
		.name		= "gnss-nrst",
		.gpio		= 132,
		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
	}, {
		.name		= "bt-wakeup",
		.gpio		= 232,
		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
	}, {
		.name		= "strobe",
		.gpio		= 250,
		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
	}, {
		.name		= "bbresetout",
		.gpio		= 288,
		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
	},
};

static __initdata struct gpio_led_platform_data ape6evm_leds_pdata = {
	.leds		= ape6evm_leds,
	.num_leds	= ARRAY_SIZE(ape6evm_leds),
};

74 75 76 77 78 79 80 81 82 83 84 85 86
/* GPIO KEY */
#define GPIO_KEY(c, g, d, ...) \
	{ .code = c, .gpio = g, .desc = d, .active_low = 1 }

static struct gpio_keys_button gpio_buttons[] = {
	GPIO_KEY(KEY_0,			324,	"S16"),
	GPIO_KEY(KEY_MENU,		325,	"S17"),
	GPIO_KEY(KEY_HOME,		326,	"S18"),
	GPIO_KEY(KEY_BACK,		327,	"S19"),
	GPIO_KEY(KEY_VOLUMEUP,		328,	"S20"),
	GPIO_KEY(KEY_VOLUMEDOWN,	329,	"S21"),
};

87
static struct gpio_keys_platform_data ape6evm_keys_pdata __initdata = {
88 89 90 91
	.buttons	= gpio_buttons,
	.nbuttons	= ARRAY_SIZE(gpio_buttons),
};

92 93 94 95 96 97 98
/* Dummy supplies, where voltage doesn't matter */
static struct regulator_consumer_supply dummy_supplies[] = {
	REGULATOR_SUPPLY("vddvario", "smsc911x"),
	REGULATOR_SUPPLY("vdd33a", "smsc911x"),
};

/* SMSC LAN9220 */
99
static const struct resource lan9220_res[] __initconst = {
100 101 102 103 104 105 106
	DEFINE_RES_MEM(0x08000000, 0x1000),
	{
		.start	= irq_pin(40), /* IRQ40 */
		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
	},
};

107
static const struct smsc911x_platform_config lan9220_data __initconst = {
108 109 110 111 112
	.flags		= SMSC911X_USE_32BIT,
	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
};

113
/*
114 115 116 117
 * MMC0 power supplies:
 * Both Vcc and VccQ to eMMC on APE6EVM are supplied by a tps80032 voltage
 * regulator. Until support for it is added to this file we simulate the
 * Vcc supply by a fixed always-on regulator
118
 */
119
static struct regulator_consumer_supply vcc_mmc0_consumers[] =
120 121
{
	REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"),
122 123 124 125 126 127 128 129 130 131
};

/*
 * SDHI0 power supplies:
 * Vcc to SDHI0 on APE6EVM is supplied by a GPIO-switchable regulator. VccQ is
 * provided by the same tps80032 regulator as both MMC0 voltages - see comment
 * above
 */
static struct regulator_consumer_supply vcc_sdhi0_consumers[] =
{
132
	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
};

static struct regulator_init_data vcc_sdhi0_init_data = {
	.constraints = {
		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
	},
	.num_consumer_supplies  = ARRAY_SIZE(vcc_sdhi0_consumers),
	.consumer_supplies      = vcc_sdhi0_consumers,
};

static const struct fixed_voltage_config vcc_sdhi0_info __initconst = {
	.supply_name = "SDHI0 Vcc",
	.microvolts = 3300000,
	.gpio = 76,
	.enable_high = 1,
	.init_data = &vcc_sdhi0_init_data,
};

/*
 * SDHI1 power supplies:
 * Vcc and VccQ to SDHI1 on APE6EVM are both fixed at 3.3V
 */
static struct regulator_consumer_supply vcc_sdhi1_consumers[] =
{
157
	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
158 159 160
};

/* MMCIF */
161
static const struct sh_mmcif_plat_data mmcif0_pdata __initconst = {
162
	.caps		= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
163 164
	.slave_id_tx	= SHDMA_SLAVE_MMCIF0_TX,
	.slave_id_rx	= SHDMA_SLAVE_MMCIF0_RX,
165
	.ccs_unsupported = true,
166 167
};

168
static const struct resource mmcif0_resources[] __initconst = {
169
	DEFINE_RES_MEM(0xee200000, 0x100),
170 171 172
	DEFINE_RES_IRQ(gic_spi(169)),
};

173
/* SDHI0 */
174
static const struct sh_mobile_sdhi_info sdhi0_pdata __initconst = {
175 176 177 178
	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE,
	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
};

179
static const struct resource sdhi0_resources[] __initconst = {
180
	DEFINE_RES_MEM(0xee100000, 0x100),
181 182 183 184
	DEFINE_RES_IRQ(gic_spi(165)),
};

/* SDHI1 */
185
static const struct sh_mobile_sdhi_info sdhi1_pdata __initconst = {
186 187 188 189 190
	.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,
};

191
static const struct resource sdhi1_resources[] __initconst = {
192
	DEFINE_RES_MEM(0xee120000, 0x100),
193 194 195
	DEFINE_RES_IRQ(gic_spi(166)),
};

196
static const struct pinctrl_map ape6evm_pinctrl_map[] __initconst = {
M
Magnus Damm 已提交
197 198 199
	/* SCIFA0 console */
	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a73a4",
				  "scifa0_data", "scifa0"),
200 201 202
	/* SMSC */
	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a73a4",
				  "irqc_irq40", "irqc"),
203 204 205 206 207
	/* 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"),
208 209 210 211 212 213 214 215 216 217 218 219
	/* 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"),
M
Magnus Damm 已提交
220 221
};

222 223
static void __init ape6evm_add_standard_devices(void)
{
224 225 226 227

	struct clk *parent;
	struct clk *mp;

228
	r8a73a4_clock_init();
229 230 231 232 233 234 235 236 237 238

	/* MP clock parent = extal2 */
	parent      = clk_get(NULL, "extal2");
	mp          = clk_get(NULL, "mp");
	BUG_ON(IS_ERR(parent) || IS_ERR(mp));

	clk_set_parent(mp, parent);
	clk_put(parent);
	clk_put(mp);

M
Magnus Damm 已提交
239 240 241
	pinctrl_register_mappings(ape6evm_pinctrl_map,
				  ARRAY_SIZE(ape6evm_pinctrl_map));
	r8a73a4_pinmux_init();
242
	r8a73a4_add_standard_devices();
243 244 245 246 247 248

	/* LAN9220 ethernet */
	gpio_request_one(270, GPIOF_OUT_INIT_HIGH, NULL); /* smsc9220 RESET */

	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));

249
	platform_device_register_resndata(NULL, "smsc911x", -1,
250 251
					  lan9220_res, ARRAY_SIZE(lan9220_res),
					  &lan9220_data, sizeof(lan9220_data));
252 253 254

	regulator_register_always_on(1, "MMC0 Vcc", vcc_mmc0_consumers,
				     ARRAY_SIZE(vcc_mmc0_consumers), 2800000);
255
	platform_device_register_resndata(NULL, "sh_mmcif", 0,
256 257
					  mmcif0_resources, ARRAY_SIZE(mmcif0_resources),
					  &mmcif0_pdata, sizeof(mmcif0_pdata));
258
	platform_device_register_data(NULL, "reg-fixed-voltage", 2,
259
				      &vcc_sdhi0_info, sizeof(vcc_sdhi0_info));
260
	platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
261 262
					  sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
					  &sdhi0_pdata, sizeof(sdhi0_pdata));
263 264
	regulator_register_always_on(3, "SDHI1 Vcc", vcc_sdhi1_consumers,
				     ARRAY_SIZE(vcc_sdhi1_consumers), 3300000);
265
	platform_device_register_resndata(NULL, "sh_mobile_sdhi", 1,
266 267
					  sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
					  &sdhi1_pdata, sizeof(sdhi1_pdata));
268
	platform_device_register_data(NULL, "gpio-keys", -1,
269 270
				      &ape6evm_keys_pdata,
				      sizeof(ape6evm_keys_pdata));
271
	platform_device_register_data(NULL, "leds-gpio", -1,
272 273
				      &ape6evm_leds_pdata,
				      sizeof(ape6evm_leds_pdata));
274 275 276 277 278 279 280 281
}

static const char *ape6evm_boards_compat_dt[] __initdata = {
	"renesas,ape6evm",
	NULL,
};

DT_MACHINE_START(APE6EVM_DT, "ape6evm")
282
	.init_early	= shmobile_init_delay,
283
	.init_machine	= ape6evm_add_standard_devices,
284
	.init_late	= shmobile_init_late,
285 286
	.dt_compat	= ape6evm_boards_compat_dt,
MACHINE_END