102bf6cc7SPaul Mundt /* 202bf6cc7SPaul Mundt * Renesas Technology Europe SDK7786 Support. 302bf6cc7SPaul Mundt * 402bf6cc7SPaul Mundt * Copyright (C) 2010 Matt Fleming 502bf6cc7SPaul Mundt * Copyright (C) 2010 Paul Mundt 602bf6cc7SPaul Mundt * 702bf6cc7SPaul Mundt * This file is subject to the terms and conditions of the GNU General Public 802bf6cc7SPaul Mundt * License. See the file "COPYING" in the main directory of this archive 902bf6cc7SPaul Mundt * for more details. 1002bf6cc7SPaul Mundt */ 1102bf6cc7SPaul Mundt #include <linux/init.h> 1202bf6cc7SPaul Mundt #include <linux/platform_device.h> 1302bf6cc7SPaul Mundt #include <linux/io.h> 14*2fcfe22aSGuennadi Liakhovetski #include <linux/regulator/fixed.h> 15*2fcfe22aSGuennadi Liakhovetski #include <linux/regulator/machine.h> 1602bf6cc7SPaul Mundt #include <linux/smsc911x.h> 1702bf6cc7SPaul Mundt #include <linux/i2c.h> 1802bf6cc7SPaul Mundt #include <linux/irq.h> 19c8098218SPaul Mundt #include <linux/clk.h> 203bd75e5eSPaul Mundt #include <linux/clkdev.h> 215f240718SPaul Mundt #include <mach/fpga.h> 225f240718SPaul Mundt #include <mach/irq.h> 2302bf6cc7SPaul Mundt #include <asm/machvec.h> 242267c787SPaul Mundt #include <asm/heartbeat.h> 2502bf6cc7SPaul Mundt #include <asm/sizes.h> 26b6b77b2dSPaul Mundt #include <asm/clock.h> 27b51989b8SPaul Mundt #include <asm/reboot.h> 283366e358SPaul Mundt #include <asm/smp-ops.h> 2902bf6cc7SPaul Mundt 302267c787SPaul Mundt static struct resource heartbeat_resource = { 312267c787SPaul Mundt .start = 0x07fff8b0, 322267c787SPaul Mundt .end = 0x07fff8b0 + sizeof(u16) - 1, 332267c787SPaul Mundt .flags = IORESOURCE_MEM | IORESOURCE_MEM_16BIT, 342267c787SPaul Mundt }; 352267c787SPaul Mundt 362267c787SPaul Mundt static struct platform_device heartbeat_device = { 372267c787SPaul Mundt .name = "heartbeat", 382267c787SPaul Mundt .id = -1, 392267c787SPaul Mundt .num_resources = 1, 402267c787SPaul Mundt .resource = &heartbeat_resource, 412267c787SPaul Mundt }; 422267c787SPaul Mundt 43*2fcfe22aSGuennadi Liakhovetski /* Dummy supplies, where voltage doesn't matter */ 44*2fcfe22aSGuennadi Liakhovetski static struct regulator_consumer_supply dummy_supplies[] = { 45*2fcfe22aSGuennadi Liakhovetski REGULATOR_SUPPLY("vddvario", "smsc911x"), 46*2fcfe22aSGuennadi Liakhovetski REGULATOR_SUPPLY("vdd33a", "smsc911x"), 47*2fcfe22aSGuennadi Liakhovetski }; 48*2fcfe22aSGuennadi Liakhovetski 4902bf6cc7SPaul Mundt static struct resource smsc911x_resources[] = { 5002bf6cc7SPaul Mundt [0] = { 5102bf6cc7SPaul Mundt .name = "smsc911x-memory", 5202bf6cc7SPaul Mundt .start = 0x07ffff00, 5302bf6cc7SPaul Mundt .end = 0x07ffff00 + SZ_256 - 1, 5402bf6cc7SPaul Mundt .flags = IORESOURCE_MEM, 5502bf6cc7SPaul Mundt }, 5602bf6cc7SPaul Mundt [1] = { 5702bf6cc7SPaul Mundt .name = "smsc911x-irq", 5802bf6cc7SPaul Mundt .start = evt2irq(0x2c0), 5902bf6cc7SPaul Mundt .end = evt2irq(0x2c0), 6002bf6cc7SPaul Mundt .flags = IORESOURCE_IRQ, 6102bf6cc7SPaul Mundt }, 6202bf6cc7SPaul Mundt }; 6302bf6cc7SPaul Mundt 6402bf6cc7SPaul Mundt static struct smsc911x_platform_config smsc911x_config = { 6502bf6cc7SPaul Mundt .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, 6602bf6cc7SPaul Mundt .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, 6702bf6cc7SPaul Mundt .flags = SMSC911X_USE_32BIT, 6802bf6cc7SPaul Mundt .phy_interface = PHY_INTERFACE_MODE_MII, 6902bf6cc7SPaul Mundt }; 7002bf6cc7SPaul Mundt 7102bf6cc7SPaul Mundt static struct platform_device smsc911x_device = { 7202bf6cc7SPaul Mundt .name = "smsc911x", 7302bf6cc7SPaul Mundt .id = -1, 7402bf6cc7SPaul Mundt .num_resources = ARRAY_SIZE(smsc911x_resources), 7502bf6cc7SPaul Mundt .resource = smsc911x_resources, 7602bf6cc7SPaul Mundt .dev = { 7702bf6cc7SPaul Mundt .platform_data = &smsc911x_config, 7802bf6cc7SPaul Mundt }, 7902bf6cc7SPaul Mundt }; 8002bf6cc7SPaul Mundt 8102bf6cc7SPaul Mundt static struct resource smbus_fpga_resource = { 8202bf6cc7SPaul Mundt .start = 0x07fff9e0, 8302bf6cc7SPaul Mundt .end = 0x07fff9e0 + SZ_32 - 1, 8402bf6cc7SPaul Mundt .flags = IORESOURCE_MEM, 8502bf6cc7SPaul Mundt }; 8602bf6cc7SPaul Mundt 8702bf6cc7SPaul Mundt static struct platform_device smbus_fpga_device = { 8802bf6cc7SPaul Mundt .name = "i2c-sdk7786", 8902bf6cc7SPaul Mundt .id = 0, 9002bf6cc7SPaul Mundt .num_resources = 1, 9102bf6cc7SPaul Mundt .resource = &smbus_fpga_resource, 9202bf6cc7SPaul Mundt }; 9302bf6cc7SPaul Mundt 9402bf6cc7SPaul Mundt static struct resource smbus_pcie_resource = { 9502bf6cc7SPaul Mundt .start = 0x07fffc30, 9602bf6cc7SPaul Mundt .end = 0x07fffc30 + SZ_32 - 1, 9702bf6cc7SPaul Mundt .flags = IORESOURCE_MEM, 9802bf6cc7SPaul Mundt }; 9902bf6cc7SPaul Mundt 10002bf6cc7SPaul Mundt static struct platform_device smbus_pcie_device = { 10102bf6cc7SPaul Mundt .name = "i2c-sdk7786", 10202bf6cc7SPaul Mundt .id = 1, 10302bf6cc7SPaul Mundt .num_resources = 1, 10402bf6cc7SPaul Mundt .resource = &smbus_pcie_resource, 10502bf6cc7SPaul Mundt }; 10602bf6cc7SPaul Mundt 10702bf6cc7SPaul Mundt static struct i2c_board_info __initdata sdk7786_i2c_devices[] = { 10802bf6cc7SPaul Mundt { 10902bf6cc7SPaul Mundt I2C_BOARD_INFO("max6900", 0x68), 11002bf6cc7SPaul Mundt }, 11102bf6cc7SPaul Mundt }; 11202bf6cc7SPaul Mundt 11302bf6cc7SPaul Mundt static struct platform_device *sh7786_devices[] __initdata = { 1142267c787SPaul Mundt &heartbeat_device, 11502bf6cc7SPaul Mundt &smsc911x_device, 11602bf6cc7SPaul Mundt &smbus_fpga_device, 11702bf6cc7SPaul Mundt &smbus_pcie_device, 11802bf6cc7SPaul Mundt }; 11902bf6cc7SPaul Mundt 12002bf6cc7SPaul Mundt static int sdk7786_i2c_setup(void) 12102bf6cc7SPaul Mundt { 12202bf6cc7SPaul Mundt unsigned int tmp; 12302bf6cc7SPaul Mundt 12402bf6cc7SPaul Mundt /* 12502bf6cc7SPaul Mundt * Hand over I2C control to the FPGA. 12602bf6cc7SPaul Mundt */ 127efd590d5SPaul Mundt tmp = fpga_read_reg(SBCR); 12802bf6cc7SPaul Mundt tmp &= ~SCBR_I2CCEN; 12902bf6cc7SPaul Mundt tmp |= SCBR_I2CMEN; 130efd590d5SPaul Mundt fpga_write_reg(tmp, SBCR); 13102bf6cc7SPaul Mundt 13202bf6cc7SPaul Mundt return i2c_register_board_info(0, sdk7786_i2c_devices, 13302bf6cc7SPaul Mundt ARRAY_SIZE(sdk7786_i2c_devices)); 13402bf6cc7SPaul Mundt } 13502bf6cc7SPaul Mundt 13602bf6cc7SPaul Mundt static int __init sdk7786_devices_setup(void) 13702bf6cc7SPaul Mundt { 13802bf6cc7SPaul Mundt int ret; 13902bf6cc7SPaul Mundt 14002bf6cc7SPaul Mundt ret = platform_add_devices(sh7786_devices, ARRAY_SIZE(sh7786_devices)); 14102bf6cc7SPaul Mundt if (unlikely(ret != 0)) 14202bf6cc7SPaul Mundt return ret; 14302bf6cc7SPaul Mundt 14402bf6cc7SPaul Mundt return sdk7786_i2c_setup(); 14502bf6cc7SPaul Mundt } 14695d210ceSNobuhiro Iwamatsu device_initcall(sdk7786_devices_setup); 14702bf6cc7SPaul Mundt 1486f832e8aSPaul Mundt static int sdk7786_mode_pins(void) 1496f832e8aSPaul Mundt { 150efd590d5SPaul Mundt return fpga_read_reg(MODSWR); 1516f832e8aSPaul Mundt } 1526f832e8aSPaul Mundt 153b6b77b2dSPaul Mundt /* 154b6b77b2dSPaul Mundt * FPGA-driven PCIe clocks 155b6b77b2dSPaul Mundt * 156b6b77b2dSPaul Mundt * Historically these include the oscillator, clock B (slots 2/3/4) and 157b6b77b2dSPaul Mundt * clock A (slot 1 and the CPU clock). Newer revs of the PCB shove 158b6b77b2dSPaul Mundt * everything under a single PCIe clocks enable bit that happens to map 159b6b77b2dSPaul Mundt * to the same bit position as the oscillator bit for earlier FPGA 160b6b77b2dSPaul Mundt * versions. 161b6b77b2dSPaul Mundt * 162b6b77b2dSPaul Mundt * Given that the legacy clocks have the side-effect of shutting the CPU 163b6b77b2dSPaul Mundt * off through the FPGA along with the PCI slots, we simply leave them in 164b6b77b2dSPaul Mundt * their initial state and don't bother registering them with the clock 165b6b77b2dSPaul Mundt * framework. 166b6b77b2dSPaul Mundt */ 167b6b77b2dSPaul Mundt static int sdk7786_pcie_clk_enable(struct clk *clk) 168b6b77b2dSPaul Mundt { 169b6b77b2dSPaul Mundt fpga_write_reg(fpga_read_reg(PCIECR) | PCIECR_CLKEN, PCIECR); 170b6b77b2dSPaul Mundt return 0; 171b6b77b2dSPaul Mundt } 172b6b77b2dSPaul Mundt 173b6b77b2dSPaul Mundt static void sdk7786_pcie_clk_disable(struct clk *clk) 174b6b77b2dSPaul Mundt { 175b6b77b2dSPaul Mundt fpga_write_reg(fpga_read_reg(PCIECR) & ~PCIECR_CLKEN, PCIECR); 176b6b77b2dSPaul Mundt } 177b6b77b2dSPaul Mundt 178c953efdbSMagnus Damm static struct sh_clk_ops sdk7786_pcie_clk_ops = { 179b6b77b2dSPaul Mundt .enable = sdk7786_pcie_clk_enable, 180b6b77b2dSPaul Mundt .disable = sdk7786_pcie_clk_disable, 181b6b77b2dSPaul Mundt }; 182b6b77b2dSPaul Mundt 183b6b77b2dSPaul Mundt static struct clk sdk7786_pcie_clk = { 184b6b77b2dSPaul Mundt .ops = &sdk7786_pcie_clk_ops, 185b6b77b2dSPaul Mundt }; 186b6b77b2dSPaul Mundt 187b6b77b2dSPaul Mundt static struct clk_lookup sdk7786_pcie_cl = { 188b6b77b2dSPaul Mundt .con_id = "pcie_plat_clk", 189b6b77b2dSPaul Mundt .clk = &sdk7786_pcie_clk, 190b6b77b2dSPaul Mundt }; 191b6b77b2dSPaul Mundt 192c8098218SPaul Mundt static int sdk7786_clk_init(void) 193c8098218SPaul Mundt { 194c8098218SPaul Mundt struct clk *clk; 195c8098218SPaul Mundt int ret; 196c8098218SPaul Mundt 197c8098218SPaul Mundt /* 198c8098218SPaul Mundt * Only handle the EXTAL case, anyone interfacing a crystal 199c8098218SPaul Mundt * resonator will need to provide their own input clock. 200c8098218SPaul Mundt */ 201c8098218SPaul Mundt if (test_mode_pin(MODE_PIN9)) 202c8098218SPaul Mundt return -EINVAL; 203c8098218SPaul Mundt 204c8098218SPaul Mundt clk = clk_get(NULL, "extal"); 2057912825dSPaul Mundt if (IS_ERR(clk)) 206c8098218SPaul Mundt return PTR_ERR(clk); 207c8098218SPaul Mundt ret = clk_set_rate(clk, 33333333); 208c8098218SPaul Mundt clk_put(clk); 209c8098218SPaul Mundt 210b6b77b2dSPaul Mundt /* 211b6b77b2dSPaul Mundt * Setup the FPGA clocks. 212b6b77b2dSPaul Mundt */ 213b6b77b2dSPaul Mundt ret = clk_register(&sdk7786_pcie_clk); 214b6b77b2dSPaul Mundt if (unlikely(ret)) { 215b6b77b2dSPaul Mundt pr_err("FPGA clock registration failed\n"); 216c8098218SPaul Mundt return ret; 217c8098218SPaul Mundt } 218c8098218SPaul Mundt 219b6b77b2dSPaul Mundt clkdev_add(&sdk7786_pcie_cl); 220b6b77b2dSPaul Mundt 221b6b77b2dSPaul Mundt return 0; 222b6b77b2dSPaul Mundt } 223b6b77b2dSPaul Mundt 224b51989b8SPaul Mundt static void sdk7786_restart(char *cmd) 225b51989b8SPaul Mundt { 226b51989b8SPaul Mundt fpga_write_reg(0xa5a5, SRSTR); 227b51989b8SPaul Mundt } 228b51989b8SPaul Mundt 229d9c94446SPaul Mundt static void sdk7786_power_off(void) 230d9c94446SPaul Mundt { 231d9c94446SPaul Mundt fpga_write_reg(fpga_read_reg(PWRCR) | PWRCR_PDWNREQ, PWRCR); 232d9c94446SPaul Mundt 233d9c94446SPaul Mundt /* 234d9c94446SPaul Mundt * It can take up to 20us for the R8C to do its job, back off and 235d9c94446SPaul Mundt * wait a bit until we've been shut off. Even though newer FPGA 236d9c94446SPaul Mundt * versions don't set the ACK bit, the latency issue remains. 237d9c94446SPaul Mundt */ 238d9c94446SPaul Mundt while ((fpga_read_reg(PWRCR) & PWRCR_PDWNACK) == 0) 239d9c94446SPaul Mundt cpu_sleep(); 240d9c94446SPaul Mundt } 241d9c94446SPaul Mundt 24202bf6cc7SPaul Mundt /* Initialize the board */ 24302bf6cc7SPaul Mundt static void __init sdk7786_setup(char **cmdline_p) 24402bf6cc7SPaul Mundt { 245efd590d5SPaul Mundt pr_info("Renesas Technology Europe SDK7786 support:\n"); 246efd590d5SPaul Mundt 247*2fcfe22aSGuennadi Liakhovetski regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); 248*2fcfe22aSGuennadi Liakhovetski 249efd590d5SPaul Mundt sdk7786_fpga_init(); 25076496f8fSPaul Mundt sdk7786_nmi_init(); 251efd590d5SPaul Mundt 252efd590d5SPaul Mundt pr_info("\tPCB revision:\t%d\n", fpga_read_reg(PCBRR) & 0xf); 253b51989b8SPaul Mundt 254b51989b8SPaul Mundt machine_ops.restart = sdk7786_restart; 255d9c94446SPaul Mundt pm_power_off = sdk7786_power_off; 2563366e358SPaul Mundt 2573366e358SPaul Mundt register_smp_ops(&shx3_smp_ops); 25802bf6cc7SPaul Mundt } 25902bf6cc7SPaul Mundt 26002bf6cc7SPaul Mundt /* 26102bf6cc7SPaul Mundt * The Machine Vector 26202bf6cc7SPaul Mundt */ 26302bf6cc7SPaul Mundt static struct sh_machine_vector mv_sdk7786 __initmv = { 26402bf6cc7SPaul Mundt .mv_name = "SDK7786", 26502bf6cc7SPaul Mundt .mv_setup = sdk7786_setup, 2666f832e8aSPaul Mundt .mv_mode_pins = sdk7786_mode_pins, 267c8098218SPaul Mundt .mv_clk_init = sdk7786_clk_init, 2685f240718SPaul Mundt .mv_init_irq = sdk7786_init_irq, 26902bf6cc7SPaul Mundt }; 270