1/* 2 * marzen board support 3 * 4 * Copyright (C) 2011, 2013 Renesas Solutions Corp. 5 * Copyright (C) 2011 Magnus Damm 6 * Copyright (C) 2013 Cogent Embedded, Inc. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; version 2 of the License. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include <linux/kernel.h> 23#include <linux/init.h> 24#include <linux/interrupt.h> 25#include <linux/irq.h> 26#include <linux/platform_device.h> 27#include <linux/delay.h> 28#include <linux/io.h> 29#include <linux/leds.h> 30#include <linux/dma-mapping.h> 31#include <linux/pinctrl/machine.h> 32#include <linux/platform_data/camera-rcar.h> 33#include <linux/platform_data/gpio-rcar.h> 34#include <linux/platform_data/rcar-du.h> 35#include <linux/platform_data/usb-rcar-phy.h> 36#include <linux/regulator/fixed.h> 37#include <linux/regulator/machine.h> 38#include <linux/smsc911x.h> 39#include <linux/spi/spi.h> 40#include <linux/spi/sh_hspi.h> 41#include <linux/mmc/host.h> 42#include <linux/mmc/sh_mobile_sdhi.h> 43#include <linux/mfd/tmio.h> 44 45#include <media/soc_camera.h> 46#include <asm/mach-types.h> 47#include <asm/mach/arch.h> 48#include <asm/traps.h> 49 50#include "common.h" 51#include "irqs.h" 52#include "r8a7779.h" 53 54/* Fixed 3.3V regulator to be used by SDHI0 */ 55static struct regulator_consumer_supply fixed3v3_power_consumers[] = { 56 REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), 57 REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"), 58}; 59 60/* Dummy supplies, where voltage doesn't matter */ 61static struct regulator_consumer_supply dummy_supplies[] = { 62 REGULATOR_SUPPLY("vddvario", "smsc911x"), 63 REGULATOR_SUPPLY("vdd33a", "smsc911x"), 64}; 65 66/* USB PHY */ 67static struct resource usb_phy_resources[] = { 68 [0] = { 69 .start = 0xffe70800, 70 .end = 0xffe70900 - 1, 71 .flags = IORESOURCE_MEM, 72 }, 73}; 74 75static struct rcar_phy_platform_data usb_phy_platform_data; 76 77static struct platform_device usb_phy = { 78 .name = "rcar_usb_phy", 79 .id = -1, 80 .dev = { 81 .platform_data = &usb_phy_platform_data, 82 }, 83 .resource = usb_phy_resources, 84 .num_resources = ARRAY_SIZE(usb_phy_resources), 85}; 86 87/* SMSC LAN89218 */ 88static struct resource smsc911x_resources[] = { 89 [0] = { 90 .start = 0x18000000, /* ExCS0 */ 91 .end = 0x180000ff, /* A1->A7 */ 92 .flags = IORESOURCE_MEM, 93 }, 94 [1] = { 95 .start = irq_pin(1), /* IRQ 1 */ 96 .flags = IORESOURCE_IRQ, 97 }, 98}; 99 100static struct smsc911x_platform_config smsc911x_platdata = { 101 .flags = SMSC911X_USE_32BIT, /* 32-bit SW on 16-bit HW bus */ 102 .phy_interface = PHY_INTERFACE_MODE_MII, 103 .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, 104 .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, 105}; 106 107static struct platform_device eth_device = { 108 .name = "smsc911x", 109 .id = -1, 110 .dev = { 111 .platform_data = &smsc911x_platdata, 112 }, 113 .resource = smsc911x_resources, 114 .num_resources = ARRAY_SIZE(smsc911x_resources), 115}; 116 117static struct resource sdhi0_resources[] = { 118 [0] = { 119 .name = "sdhi0", 120 .start = 0xffe4c000, 121 .end = 0xffe4c0ff, 122 .flags = IORESOURCE_MEM, 123 }, 124 [1] = { 125 .start = gic_iid(0x88), 126 .flags = IORESOURCE_IRQ, 127 }, 128}; 129 130static struct sh_mobile_sdhi_info sdhi0_platform_data = { 131 .dma_slave_tx = HPBDMA_SLAVE_SDHI0_TX, 132 .dma_slave_rx = HPBDMA_SLAVE_SDHI0_RX, 133 .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT, 134 .tmio_caps = MMC_CAP_SD_HIGHSPEED, 135}; 136 137static struct platform_device sdhi0_device = { 138 .name = "sh_mobile_sdhi", 139 .num_resources = ARRAY_SIZE(sdhi0_resources), 140 .resource = sdhi0_resources, 141 .id = 0, 142 .dev = { 143 .platform_data = &sdhi0_platform_data, 144 } 145}; 146 147/* Thermal */ 148static struct resource thermal_resources[] = { 149 [0] = { 150 .start = 0xFFC48000, 151 .end = 0xFFC48038 - 1, 152 .flags = IORESOURCE_MEM, 153 }, 154}; 155 156static struct platform_device thermal_device = { 157 .name = "rcar_thermal", 158 .resource = thermal_resources, 159 .num_resources = ARRAY_SIZE(thermal_resources), 160}; 161 162/* HSPI */ 163static struct resource hspi_resources[] = { 164 [0] = { 165 .start = 0xFFFC7000, 166 .end = 0xFFFC7018 - 1, 167 .flags = IORESOURCE_MEM, 168 }, 169}; 170 171static struct platform_device hspi_device = { 172 .name = "sh-hspi", 173 .id = 0, 174 .resource = hspi_resources, 175 .num_resources = ARRAY_SIZE(hspi_resources), 176}; 177 178/* 179 * DU 180 * 181 * The panel only specifies the [hv]display and [hv]total values. The position 182 * and width of the sync pulses don't matter, they're copied from VESA timings. 183 */ 184static struct rcar_du_encoder_data du_encoders[] = { 185 { 186 .type = RCAR_DU_ENCODER_VGA, 187 .output = RCAR_DU_OUTPUT_DPAD0, 188 }, { 189 .type = RCAR_DU_ENCODER_LVDS, 190 .output = RCAR_DU_OUTPUT_DPAD1, 191 .connector.lvds.panel = { 192 .width_mm = 210, 193 .height_mm = 158, 194 .mode = { 195 .pixelclock = 65000000, 196 .hactive = 1024, 197 .hfront_porch = 20, 198 .hback_porch = 160, 199 .hsync_len = 136, 200 .vactive = 768, 201 .vfront_porch = 3, 202 .vback_porch = 29, 203 .vsync_len = 6, 204 }, 205 }, 206 }, 207}; 208 209static const struct rcar_du_platform_data du_pdata __initconst = { 210 .encoders = du_encoders, 211 .num_encoders = ARRAY_SIZE(du_encoders), 212}; 213 214static const struct resource du_resources[] __initconst = { 215 DEFINE_RES_MEM(0xfff80000, 0x40000), 216 DEFINE_RES_IRQ(gic_iid(0x3f)), 217}; 218 219static void __init marzen_add_du_device(void) 220{ 221 struct platform_device_info info = { 222 .name = "rcar-du-r8a7779", 223 .id = -1, 224 .res = du_resources, 225 .num_res = ARRAY_SIZE(du_resources), 226 .data = &du_pdata, 227 .size_data = sizeof(du_pdata), 228 .dma_mask = DMA_BIT_MASK(32), 229 }; 230 231 platform_device_register_full(&info); 232} 233 234/* LEDS */ 235static struct gpio_led marzen_leds[] = { 236 { 237 .name = "led2", 238 .gpio = RCAR_GP_PIN(4, 29), 239 .default_state = LEDS_GPIO_DEFSTATE_ON, 240 }, { 241 .name = "led3", 242 .gpio = RCAR_GP_PIN(4, 30), 243 .default_state = LEDS_GPIO_DEFSTATE_ON, 244 }, { 245 .name = "led4", 246 .gpio = RCAR_GP_PIN(4, 31), 247 .default_state = LEDS_GPIO_DEFSTATE_ON, 248 }, 249}; 250 251static struct gpio_led_platform_data marzen_leds_pdata = { 252 .leds = marzen_leds, 253 .num_leds = ARRAY_SIZE(marzen_leds), 254}; 255 256static struct platform_device leds_device = { 257 .name = "leds-gpio", 258 .id = 0, 259 .dev = { 260 .platform_data = &marzen_leds_pdata, 261 }, 262}; 263 264/* VIN */ 265static struct rcar_vin_platform_data vin_platform_data __initdata = { 266 .flags = RCAR_VIN_BT656, 267}; 268 269#define MARZEN_VIN(idx) \ 270static struct resource vin##idx##_resources[] __initdata = { \ 271 DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000), \ 272 DEFINE_RES_IRQ(gic_iid(0x5f + (idx))), \ 273}; \ 274 \ 275static struct platform_device_info vin##idx##_info __initdata = { \ 276 .name = "r8a7779-vin", \ 277 .id = idx, \ 278 .res = vin##idx##_resources, \ 279 .num_res = ARRAY_SIZE(vin##idx##_resources), \ 280 .dma_mask = DMA_BIT_MASK(32), \ 281 .data = &vin_platform_data, \ 282 .size_data = sizeof(vin_platform_data), \ 283} 284MARZEN_VIN(1); 285MARZEN_VIN(3); 286 287#define MARZEN_CAMERA(idx) \ 288static struct i2c_board_info camera##idx##_info = { \ 289 I2C_BOARD_INFO("adv7180", 0x20 + (idx)), \ 290}; \ 291 \ 292static struct soc_camera_link iclink##idx##_adv7180 = { \ 293 .bus_id = 1 + 2 * (idx), \ 294 .i2c_adapter_id = 0, \ 295 .board_info = &camera##idx##_info, \ 296}; \ 297 \ 298static struct platform_device camera##idx##_device = { \ 299 .name = "soc-camera-pdrv", \ 300 .id = idx, \ 301 .dev = { \ 302 .platform_data = &iclink##idx##_adv7180, \ 303 }, \ 304}; 305 306MARZEN_CAMERA(0); 307MARZEN_CAMERA(1); 308 309static struct platform_device *marzen_devices[] __initdata = { 310 ð_device, 311 &sdhi0_device, 312 &thermal_device, 313 &hspi_device, 314 &leds_device, 315 &usb_phy, 316 &camera0_device, 317 &camera1_device, 318}; 319 320static const struct pinctrl_map marzen_pinctrl_map[] = { 321 /* DU (CN10: ARGB0, CN13: LVDS) */ 322 PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779", 323 "du0_rgb888", "du0"), 324 PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779", 325 "du0_sync_1", "du0"), 326 PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779", 327 "du0_clk_out_0", "du0"), 328 PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779", 329 "du1_rgb666", "du1"), 330 PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779", 331 "du1_sync_1", "du1"), 332 PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779", 333 "du1_clk_out", "du1"), 334 /* HSPI0 */ 335 PIN_MAP_MUX_GROUP_DEFAULT("sh-hspi.0", "pfc-r8a7779", 336 "hspi0", "hspi0"), 337 /* SCIF2 (CN18: DEBUG0) */ 338 PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-r8a7779", 339 "scif2_data_c", "scif2"), 340 /* SCIF4 (CN19: DEBUG1) */ 341 PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-r8a7779", 342 "scif4_data", "scif4"), 343 /* SDHI0 */ 344 PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779", 345 "sdhi0_data4", "sdhi0"), 346 PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779", 347 "sdhi0_ctrl", "sdhi0"), 348 PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779", 349 "sdhi0_cd", "sdhi0"), 350 /* SMSC */ 351 PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a7779", 352 "intc_irq1_b", "intc"), 353 PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a7779", 354 "lbsc_ex_cs0", "lbsc"), 355 /* USB0 */ 356 PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.0", "pfc-r8a7779", 357 "usb0", "usb0"), 358 /* USB1 */ 359 PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.0", "pfc-r8a7779", 360 "usb1", "usb1"), 361 /* USB2 */ 362 PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.1", "pfc-r8a7779", 363 "usb2", "usb2"), 364 /* VIN1 */ 365 PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.1", "pfc-r8a7779", 366 "vin1_clk", "vin1"), 367 PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.1", "pfc-r8a7779", 368 "vin1_data8", "vin1"), 369 /* VIN3 */ 370 PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.3", "pfc-r8a7779", 371 "vin3_clk", "vin3"), 372 PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.3", "pfc-r8a7779", 373 "vin3_data8", "vin3"), 374}; 375 376static void __init marzen_init(void) 377{ 378 regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers, 379 ARRAY_SIZE(fixed3v3_power_consumers), 3300000); 380 regulator_register_fixed(1, dummy_supplies, 381 ARRAY_SIZE(dummy_supplies)); 382 383 pinctrl_register_mappings(marzen_pinctrl_map, 384 ARRAY_SIZE(marzen_pinctrl_map)); 385 r8a7779_pinmux_init(); 386 r8a7779_init_irq_extpin(1); /* IRQ1 as individual interrupt */ 387 388 r8a7779_add_standard_devices(); 389 platform_device_register_full(&vin1_info); 390 platform_device_register_full(&vin3_info); 391 platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices)); 392 marzen_add_du_device(); 393} 394 395static const char *marzen_boards_compat_dt[] __initdata = { 396 "renesas,marzen", 397 NULL, 398}; 399 400DT_MACHINE_START(MARZEN, "marzen") 401 .smp = smp_ops(r8a7779_smp_ops), 402 .map_io = r8a7779_map_io, 403 .init_early = r8a7779_add_early_devices, 404 .init_irq = r8a7779_init_irq_dt, 405 .init_machine = marzen_init, 406 .init_late = r8a7779_init_late, 407 .dt_compat = marzen_boards_compat_dt, 408 .init_time = r8a7779_earlytimer_init, 409MACHINE_END 410