Пример #1
0
static void __init wakeup_secondary(void)
{
	void __iomem *backupram;

	if (cpu_is_u8500_family() || cpu_is_ux540_family())
		backupram = __io_address(U8500_BACKUPRAM0_BASE);
	else
		ux500_unknown_soc();

	/*
	 * write the address of secondary startup into the backup ram register
	 * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
	 * backup ram register at offset 0x1FF0, which is what boot rom code
	 * is waiting for. This would wake up the secondary core from WFE
	 */
#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
	__raw_writel(virt_to_phys(u8500_secondary_startup),
		     backupram + UX500_CPU1_JUMPADDR_OFFSET);

#define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
	__raw_writel(0xA1FEED01,
		     backupram + UX500_CPU1_WAKEMAGIC_OFFSET);

	/* make sure write buffer is drained */
	mb();
}
static int __init init_display_devices(void)
{
	if (cpu_is_u8500_family())
		return handle_display_devices();
	else
		return 0;
}
Пример #3
0
/*
 * FIXME: Should we set up the GPIO domain here?
 *
 * The problem is that we cannot put the interrupt resources into the platform
 * device until the irqdomain has been added. Right now, we set the GIC interrupt
 * domain from init_irq(), then load the gpio driver from
 * core_initcall(nmk_gpio_init) and add the platform devices from
 * arch_initcall(customize_machine).
 *
 * This feels fragile because it depends on the gpio device getting probed
 * _before_ any device uses the gpio interrupts.
*/
void __init ux500_init_irq(void)
{
	gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
	irqchip_init();

	/*
	 * Init clocks here so that they are available for system timer
	 * initialization.
	 */
	if (cpu_is_u8500_family()) {
		prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
		ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);

		u8500_of_clk_init(U8500_CLKRST1_BASE,
				  U8500_CLKRST2_BASE,
				  U8500_CLKRST3_BASE,
				  U8500_CLKRST5_BASE,
				  U8500_CLKRST6_BASE);
	} else if (cpu_is_u9540()) {
		prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
		ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);
		u9540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
			       U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
			       U8500_CLKRST6_BASE);
	} else if (cpu_is_u8540()) {
		prcmu_early_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1);
		ux500_pm_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1);
		u8540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
			       U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
			       U8500_CLKRST6_BASE);
	}
}
Пример #4
0
void __init ux500_timer_init(void)
{
	void __iomem *prcmu_timer_base;
	void __iomem *tmp_base;
	struct device_node *np;

	if (cpu_is_u8500_family() || cpu_is_ux540_family())
		prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
	else
		ux500_unknown_soc();

	np = of_find_matching_node(NULL, prcmu_timer_of_match);
	if (!np)
		goto dt_fail;

	tmp_base = of_iomap(np, 0);
	if (!tmp_base)
		goto dt_fail;

	prcmu_timer_base = tmp_base;

dt_fail:
	clksrc_dbx500_prcmu_init(prcmu_timer_base);
	clocksource_of_init();
}
Пример #5
0
/*
 * FIXME: Should we set up the GPIO domain here?
 *
 * The problem is that we cannot put the interrupt resources into the platform
 * device until the irqdomain has been added. Right now, we set the GIC interrupt
 * domain from init_irq(), then load the gpio driver from
 * core_initcall(nmk_gpio_init) and add the platform devices from
 * arch_initcall(customize_machine).
 *
 * This feels fragile because it depends on the gpio device getting probed
 * _before_ any device uses the gpio interrupts.
*/
void __init ux500_init_irq(void)
{
	struct device_node *np;
	struct resource r;

	irqchip_init();
	np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu");
	of_address_to_resource(np, 0, &r);
	of_node_put(np);
	if (!r.start) {
		pr_err("could not find PRCMU base resource\n");
		return;
	}
	prcmu_early_init(r.start, r.end-r.start);
	ux500_pm_init(r.start, r.end-r.start);

	/*
	 * Init clocks here so that they are available for system timer
	 * initialization.
	 */
	if (cpu_is_u8500_family())
		u8500_clk_init();
	else if (cpu_is_u9540())
		u9540_clk_init();
	else if (cpu_is_u8540())
		u8540_clk_init();
}
Пример #6
0
static void __iomem *scu_base_addr(void)
{
	if (cpu_is_u8500_family() || cpu_is_ux540_family())
		return __io_address(U8500_SCU_BASE);
	else
		ux500_unknown_soc();

	return NULL;
}
Пример #7
0
/*
 * FIXME: Should we set up the GPIO domain here?
 *
 * The problem is that we cannot put the interrupt resources into the platform
 * device until the irqdomain has been added. Right now, we set the GIC interrupt
 * domain from init_irq(), then load the gpio driver from
 * core_initcall(nmk_gpio_init) and add the platform devices from
 * arch_initcall(customize_machine).
 *
 * This feels fragile because it depends on the gpio device getting probed
 * _before_ any device uses the gpio interrupts.
*/
void __init ux500_init_irq(void)
{
	void __iomem *dist_base;
	void __iomem *cpu_base;

	gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;

	if (cpu_is_u8500_family() || cpu_is_ux540_family()) {
		dist_base = __io_address(U8500_GIC_DIST_BASE);
		cpu_base = __io_address(U8500_GIC_CPU_BASE);
	} else
		ux500_unknown_soc();

#ifdef CONFIG_OF
	if (of_have_populated_dt())
		irqchip_init();
	else
#endif
		gic_init(0, 29, dist_base, cpu_base);

	/*
	 * Init clocks here so that they are available for system timer
	 * initialization.
	 */
	if (cpu_is_u8500_family()) {
		prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
		ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);
		u8500_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
			       U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
			       U8500_CLKRST6_BASE);
	} else if (cpu_is_u9540()) {
		prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
		ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);
		u8500_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
			       U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
			       U8500_CLKRST6_BASE);
	} else if (cpu_is_u8540()) {
		prcmu_early_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1);
		ux500_pm_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1);
		u8540_clk_init();
	}
}
bool ux500_jtag_enabled(void)
{
#ifdef CONFIG_UX500_DEBUG_NO_LAUTERBACH
	return false;
#else
	if (cpu_is_u8500_family() || cpu_is_ux540_family())
		return (product_config.rt_flags & TEE_RT_FLAGS_JTAG_ENABLED) ==
			TEE_RT_FLAGS_JTAG_ENABLED;

	return true;
#endif
}
Пример #9
0
void __init ux500_timer_init(void)
{
	void __iomem *mtu_timer_base;
	void __iomem *prcmu_timer_base;
	void __iomem *tmp_base;
	struct device_node *np;

	if (cpu_is_u8500_family() || cpu_is_ux540_family()) {
		mtu_timer_base = __io_address(U8500_MTU0_BASE);
		prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
	} else {
		ux500_unknown_soc();
	}

	/* TODO: Once MTU has been DT:ed place code above into else. */
	if (of_have_populated_dt()) {
#ifdef CONFIG_OF
		np = of_find_matching_node(NULL, prcmu_timer_of_match);
		if (!np)
#endif
			goto dt_fail;

		tmp_base = of_iomap(np, 0);
		if (!tmp_base)
			goto dt_fail;

		prcmu_timer_base = tmp_base;
	}

dt_fail:
	/* Doing it the old fashioned way. */

	/*
	 * Here we register the timerblocks active in the system.
	 * Localtimers (twd) is started when both cpu is up and running.
	 * MTU register a clocksource, clockevent and sched_clock.
	 * Since the MTU is located in the VAPE power domain
	 * it will be cleared in sleep which makes it unsuitable.
	 * We however need it as a timer tick (clockevent)
	 * during boot to calibrate delay until twd is started.
	 * RTC-RTT have problems as timer tick during boot since it is
	 * depending on delay which is not yet calibrated. RTC-RTT is in the
	 * always-on powerdomain and is used as clockevent instead of twd when
	 * sleeping.
	 * The PRCMU timer 4 register a clocksource and
	 * sched_clock with higher rating then MTU since is always-on.
	 *
	 */
	if (!of_have_populated_dt())
		nmdk_timer_init(mtu_timer_base, IRQ_MTU0);
	clksrc_dbx500_prcmu_init(prcmu_timer_base);
	ux500_twd_init();
}
Пример #10
0
static int __init ux500_l2x0_init(void)
{
	/* Multiplatform guard */
	if (!((cpu_is_u8500_family() || cpu_is_ux540_family())))
		return -ENODEV;

	/* Unlock before init */
	ux500_l2x0_unlock();
	outer_cache.write_sec = ux500_l2c310_write_sec;
	l2x0_of_init(0, ~0);

	return 0;
}
Пример #11
0
static int __init ux500_rtcrtt_init(void)
{
	if (cpu_is_u8500_family() || cpu_is_ux540_family()) {
		rtc_base  = __io_address(U8500_RTC_BASE);
	} else {
		pr_err("timer-rtt: Unknown DB Asic!\n");
		return -EINVAL;
	}

	if (request_irq(IRQ_DB8500_RTC, rtcrtt_interrupt,
			IRQF_SHARED | IRQF_NO_SUSPEND,
			"rtc-pl031-timer", rtc_base)) {
		pr_err("rtc-rtt: failed to register irq\n");
	}

	ux500_rtcrtt_measure_latency(false);
	return 0;
}
static int __init ux500_l2x0_init(void)
{
	u32 aux_val = 0x3e000000;

	if (cpu_is_u8500_family() || cpu_is_ux540_family())
		l2x0_base = __io_address(U8500_L2CC_BASE);
	else
		ux500_unknown_soc();

	/* Unlock before init */
	ux500_l2x0_unlock();

	/* DBx540's L2 has 128KB way size */
	if (cpu_is_ux540_family())
		/* 128KB way size */
		aux_val |= (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
	else
		/* 64KB way size */
		aux_val |= (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);

	/* 64KB way size, 8 way associativity, force WA */
	if (of_have_populated_dt())
		l2x0_of_init(aux_val, 0xc0000fff);
	else
		l2x0_init(l2x0_base, aux_val, 0xc0000fff);

	/*
	 * We can't disable l2 as we are in non secure mode, currently
	 * this seems be called only during kexec path. So let's
	 * override outer.disable with nasty assignment until we have
	 * some SMI service available.
	 */
	outer_cache.disable = NULL;

	return 0;
}
static int __init product_detect(void)
{
	int err;
	int origin_err;
	struct tee_operation operation = {0};
	struct tee_context context;
	struct tee_session session;

	/* Selects trustzone application needed for the job. */
	struct tee_uuid static_uuid = {
		STATIC_TEE_TA_START_LOW,
		STATIC_TEE_TA_START_MID,
		STATIC_TEE_TA_START_HIGH,
		STATIC_TEE_TA_START_CLOCKSEQ,
	};

	err = teec_initialize_context(NULL, &context);
	if (err) {
		pr_err("ux500-product: unable to initialize tee context,"
			" err = %d\n", err);
		err = -EINVAL;
		goto error0;
	}

	err = teec_open_session(&context, &session, &static_uuid,
				TEEC_LOGIN_PUBLIC, NULL, NULL, &origin_err);
	if (err) {
		pr_err("ux500-product: unable to open tee session,"
			" tee error = %d, origin error = %d\n",
			err, origin_err);
		err = -EINVAL;
		goto error1;
	}

	memset(&operation, 0, sizeof(struct tee_operation));
	if (cpu_is_u8500_family()) {
		operation.shm[0].buffer = &product_config;
		operation.shm[0].size = sizeof(product_config);
		operation.shm[0].flags = TEEC_MEM_OUTPUT;
		operation.flags = TEEC_MEMREF_0_USED;
	} else if (cpu_is_ux540_family()) {
		operation.param[0].tmpref.buffer = &product_config;
		operation.param[0].tmpref.size = sizeof(product_config);
		operation.types = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT,
						   TEEC_NONE, TEEC_NONE,
						   TEEC_NONE);
	} else {
		pr_err("ux500-product: incorrect memref\n");
		err = -EINVAL;
		goto error1;
	}

	err = teec_invoke_command(&session,
				  TEE_STA_GET_PRODUCT_CONFIG,
				  &operation, &origin_err);
	if (err) {
		pr_err("ux500-product: fetching product settings failed, err=%d",
		       err);
		err = -EINVAL;
		goto error1;
	}

	switch (product_config.product_id) {
	case TEE_PRODUCT_ID_8400:
		pr_info("ux500-product: u8400 detected\n");
		break;
	case TEE_PRODUCT_ID_8500B:
		pr_info("ux500-product: u8500B detected\n");
		break;
	case TEE_PRODUCT_ID_9500:
		pr_info("ux500-product: a9500 detected\n");
		break;
	case TEE_PRODUCT_ID_7400:
		pr_info("ux500-product: u7400 detected\n");
		break;
	case TEE_PRODUCT_ID_8500C:
		pr_info("ux500-product: u8500C detected\n");
		break;
	case TEE_PRODUCT_ID_8500A:
		pr_info("ux500-product: u8500A detected\n");
		break;
	case TEE_PRODUCT_ID_8500E:
		pr_info("ux500-product: u8500E detected\n");
		break;
	case TEE_PRODUCT_ID_8520F:
		pr_info("ux500-product: u8520F detected\n");
		break;
	case TEE_PRODUCT_ID_8520H:
		pr_info("ux500-product: u8520H detected\n");
		break;
	case TEE_PRODUCT_ID_9540:
		pr_info("ux500-product: u9540 detected\n");
		break;
	case TEE_PRODUCT_ID_9500C:
		pr_info("ux500-product: a9500C detected\n");
		break;
	case TEE_PRODUCT_ID_8500F:
		pr_info("ux500-product: u8500F detected\n");
		break;
	case TEE_PRODUCT_ID_8540APE:
		pr_info("ux500-product: u8540APE detected\n");
		break;
	case TEE_PRODUCT_ID_8540XMIP:
		pr_info("ux500-product: u8540XMIP detected\n");
		break;
	case TEE_PRODUCT_ID_8520E:
		pr_info("ux500-product: u8520E detected\n");
		break;
	case TEE_PRODUCT_ID_8520J:
		pr_info("ux500-product: u8520J detected\n");
		break;
	case TEE_PRODUCT_ID_UNKNOWN:
	default:
		pr_info("ux500-product: UNKNOWN! (0x%x) detected\n",
			product_config.product_id);
		break;
	}
	pr_info("ux500-product: JTAG is %s\n",
		ux500_jtag_enabled() ? "enabled" : "disabled");
error1:
	(void) teec_finalize_context(&context);
error0:
	return err;
}
/*
* This function will create the framebuffer for the display that is registered.
*/
static int display_postregistered_callback(struct notifier_block *nb,
	unsigned long event, void *dev)
{
	struct mcde_display_device *ddev = dev;
	u16 width, height;
	u16 virtual_height;
	struct fb_info *fbi;
#if defined(CONFIG_DISPDEV) || defined(CONFIG_COMPDEV)
	struct mcde_fb *mfb;
#endif

	if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED)
		return 0;

	if (ddev->id < 0 || ddev->id >= MCDE_NR_OF_DISPLAYS)
		return 0;

	mcde_dss_get_native_resolution(ddev, &width, &height);
	if (ddev->id == PRIMARY_DISPLAY_ID)
		virtual_height = height * 3;
	else
		virtual_height = height * 2;

#ifndef CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE
	if (ddev->id == AV8100_DISPLAY_ID)
		goto out;
#endif
	/* Create frame buffer */
#if defined(CONFIG_MCDE_DISPLAY_BAMBOOK)
	fbi = mcde_fb_create(ddev, width, height, width, virtual_height,
				ddev->default_pixel_format, FB_ROTATE_UD);
#else
	fbi = mcde_fb_create(ddev, width, height, width, virtual_height,
				ddev->default_pixel_format, FB_ROTATE_UR);
#endif

	if (IS_ERR(fbi)) {
		dev_warn(&ddev->dev,
			"Failed to create fb for display %s\n", ddev->name);
		goto display_postregistered_callback_err;
	} else {
		dev_info(&ddev->dev, "Framebuffer created (%s)\n", ddev->name);
	}

#ifdef CONFIG_DISPDEV
	mfb = to_mcde_fb(fbi);

	/* Create a dispdev overlay for this display */
	if (dispdev_create(ddev, true, mfb->ovlys[0]) < 0) {
		dev_warn(&ddev->dev,
			"Failed to create disp for display %s\n", ddev->name);
		goto display_postregistered_callback_err;
	} else {
		dev_info(&ddev->dev, "Disp dev created for (%s)\n", ddev->name);
	}
#endif

#ifdef CONFIG_COMPDEV
	/* Only create compdev for the main display */
	if (ddev->id == PRIMARY_DISPLAY_ID) {
		bool mcde_rotation = false;

		/* Use mcde rotation for U8500 only */
		if (cpu_is_u8500_family())
			mcde_rotation = true;

		mfb = to_mcde_fb(fbi);
		/* Create a compdev overlay for this display */
		if (compdev_create(ddev, mfb->ovlys[0], mcde_rotation,
					NULL) < 0) {
			dev_warn(&ddev->dev,
				"Failed to create compdev for display %s\n",
						ddev->name);
			goto display_postregistered_callback_err;
		} else {
			dev_info(&ddev->dev, "compdev created for (%s)\n",
						ddev->name);
		}
	}
#endif

out:
	return 0;

display_postregistered_callback_err:
	return -1;
}