Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f46ad023 authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge tag 'davinci-for-v4.19/soc' of...

Merge tag 'davinci-for-v4.19/soc' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci into next/soc

DaVinci SoC updates for v4.19
-----------------------------

* mach-davinci updates needed to finally move over to common clock framework
* update to use the aemif driver from drivers/memory rather than the
  private implementation available in mach-davinci

For the later item, I have included a branch from David Lechner which
should also get merged through the clk tree. The clk dependencies are
needed for aemif conversion.

* tag 'davinci-for-v4.19/soc' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci

: (34 commits)
  ARM: davinci: unduplicate aemif support
  ARM: davinci: mityomapl138: use aemif platform driver
  ARM: davinci: dm646x-evm: use aemif platform driver
  ARM: davinci: da830-evm: use aemif platform driver
  ARM: davinci: dm644x-evm: use aemif platform driver
  ARM: davinci: dm365-evm: use the ti-aemif soc driver
  ARM: davinci: da850-evm: use aemif platform driver in legacy mode
  ARM: davinci: omapl138-hawk: add aemif & nand support
  clk: davinci: psc-da830: add a lookup entry for aemif clock
  clk: davinci: psc-dm646x: use two lookup entries for the aemif clock
  clk: davinci: psc-dm644x: use two lookup entries for the aemif clock
  clk: davinci: psc-dm365: use two lookup entries for the aemif clock
  clk: davinci: psc-da850: remove the 'davinci_nand.0" lookup
  ARM: davinci: da8xx-dt: switch to device tree clocks
  ARM: davinci: add device tree support to timer
  ARM: davinci: remove legacy clocks
  ARM: davinci: da8xx: Remove legacy USB and SATA clock init
  ARM: davinci: dm646x: Remove legacy clock init
  ARM: davinci: dm644x: Remove legacy clock init
  ARM: davinci: dm365: Remove legacy clock init
  ...

Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents dd8ba523 7f69ae7f
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -606,13 +606,16 @@ config ARCH_S3C24XX
config ARCH_DAVINCI
	bool "TI DaVinci"
	select ARCH_HAS_HOLES_MEMORYMODEL
	select CLKDEV_LOOKUP
	select COMMON_CLK
	select CPU_ARM926T
	select GENERIC_ALLOCATOR
	select GENERIC_CLOCKEVENTS
	select GENERIC_IRQ_CHIP
	select GPIOLIB
	select HAVE_IDE
	select PM_GENERIC_DOMAINS if PM
	select PM_GENERIC_DOMAINS_OF if PM && OF
	select RESET_CONTROLLER
	select USE_OF
	select ZONE_DMA
	help
+1 −12
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ config MACH_DA8XX_DT
	default y
	depends on ARCH_DAVINCI_DA850
	select PINCTRL
	select TIMER_OF
	help
	  Say y here to include support for TI DaVinci DA850 based using
	  Flattened Device Tree. More information at Documentation/devicetree
@@ -231,18 +232,6 @@ config DAVINCI_MUX_WARNINGS
	  to change the pin multiplexing setup. When there are no warnings
	  printed, it's safe to deselect DAVINCI_MUX for your product.

config DAVINCI_RESET_CLOCKS
	bool "Reset unused clocks during boot"
	depends on ARCH_DAVINCI
	help
	  Say Y if you want to reset unused clocks during boot.
	  This option saves power, but assumes all drivers are
	  using the clock framework. Broken drivers that do not
	  yet use clock framework may not work with this option.
	  If you are booting from another operating system, you
	  probably do not want this option enabled until your
	  device drivers work properly.

endmenu

endif
+2 −2
Original line number Diff line number Diff line
@@ -5,8 +5,8 @@
#

# Common objects
obj-y 			:= time.o clock.o serial.o psc.o \
			   usb.o common.o sram.o aemif.o
obj-y 					:= time.o serial.o usb.o \
					   common.o sram.o

obj-$(CONFIG_DAVINCI_MUX)		+= mux.o

arch/arm/mach-davinci/aemif.c

deleted100644 → 0
+0 −218
Original line number Diff line number Diff line
/*
 * AEMIF support for DaVinci SoCs
 *
 * Copyright (C) 2010 Texas Instruments Incorporated. http://www.ti.com/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/time.h>

#include <linux/platform_data/mtd-davinci-aemif.h>
#include <linux/platform_data/mtd-davinci.h>

/* Timing value configuration */

#define TA(x)		((x) << 2)
#define RHOLD(x)	((x) << 4)
#define RSTROBE(x)	((x) << 7)
#define RSETUP(x)	((x) << 13)
#define WHOLD(x)	((x) << 17)
#define WSTROBE(x)	((x) << 20)
#define WSETUP(x)	((x) << 26)

#define TA_MAX		0x3
#define RHOLD_MAX	0x7
#define RSTROBE_MAX	0x3f
#define RSETUP_MAX	0xf
#define WHOLD_MAX	0x7
#define WSTROBE_MAX	0x3f
#define WSETUP_MAX	0xf

#define TIMING_MASK	(TA(TA_MAX) | \
				RHOLD(RHOLD_MAX) | \
				RSTROBE(RSTROBE_MAX) |	\
				RSETUP(RSETUP_MAX) | \
				WHOLD(WHOLD_MAX) | \
				WSTROBE(WSTROBE_MAX) | \
				WSETUP(WSETUP_MAX))

static inline unsigned int davinci_aemif_readl(void __iomem *base, int offset)
{
	return readl_relaxed(base + offset);
}

static inline void davinci_aemif_writel(void __iomem *base,
					int offset, unsigned long value)
{
	writel_relaxed(value, base + offset);
}

/*
 * aemif_calc_rate - calculate timing data.
 * @wanted: The cycle time needed in nanoseconds.
 * @clk: The input clock rate in kHz.
 * @max: The maximum divider value that can be programmed.
 *
 * On success, returns the calculated timing value minus 1 for easy
 * programming into AEMIF timing registers, else negative errno.
 */
static int aemif_calc_rate(int wanted, unsigned long clk, int max)
{
	int result;

	result = DIV_ROUND_UP((wanted * clk), NSEC_PER_MSEC) - 1;

	pr_debug("%s: result %d from %ld, %d\n", __func__, result, clk, wanted);

	/* It is generally OK to have a more relaxed timing than requested... */
	if (result < 0)
		result = 0;

	/* ... But configuring tighter timings is not an option. */
	else if (result > max)
		result = -EINVAL;

	return result;
}

/**
 * davinci_aemif_setup_timing - setup timing values for a given AEMIF interface
 * @t: timing values to be progammed
 * @base: The virtual base address of the AEMIF interface
 * @cs: chip-select to program the timing values for
 * @clkrate: the AEMIF clkrate
 *
 * This function programs the given timing values (in real clock) into the
 * AEMIF registers taking the AEMIF clock into account.
 *
 * This function does not use any locking while programming the AEMIF
 * because it is expected that there is only one user of a given
 * chip-select.
 *
 * Returns 0 on success, else negative errno.
 */
static int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
					void __iomem *base, unsigned cs,
					unsigned long clkrate)
{
	unsigned set, val;
	int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
	unsigned offset = A1CR_OFFSET + cs * 4;

	if (!t)
		return 0;	/* Nothing to do */

	clkrate /= 1000;	/* turn clock into kHz for ease of use */

	ta	= aemif_calc_rate(t->ta, clkrate, TA_MAX);
	rhold	= aemif_calc_rate(t->rhold, clkrate, RHOLD_MAX);
	rstrobe	= aemif_calc_rate(t->rstrobe, clkrate, RSTROBE_MAX);
	rsetup	= aemif_calc_rate(t->rsetup, clkrate, RSETUP_MAX);
	whold	= aemif_calc_rate(t->whold, clkrate, WHOLD_MAX);
	wstrobe	= aemif_calc_rate(t->wstrobe, clkrate, WSTROBE_MAX);
	wsetup	= aemif_calc_rate(t->wsetup, clkrate, WSETUP_MAX);

	if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 ||
			whold < 0 || wstrobe < 0 || wsetup < 0) {
		pr_err("%s: cannot get suitable timings\n", __func__);
		return -EINVAL;
	}

	set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) |
		WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup);

	val = __raw_readl(base + offset);
	val &= ~TIMING_MASK;
	val |= set;
	__raw_writel(val, base + offset);

	return 0;
}

/**
 * davinci_aemif_setup - setup AEMIF interface by davinci_nand_pdata
 * @pdev - link to platform device to setup settings for
 *
 * This function does not use any locking while programming the AEMIF
 * because it is expected that there is only one user of a given
 * chip-select.
 *
 * Returns 0 on success, else negative errno.
 */
int davinci_aemif_setup(struct platform_device *pdev)
{
	struct davinci_nand_pdata *pdata = dev_get_platdata(&pdev->dev);
	uint32_t val;
	unsigned long clkrate;
	struct resource	*res;
	void __iomem *base;
	struct clk *clk;
	int ret = 0;

	clk = clk_get(&pdev->dev, "aemif");
	if (IS_ERR(clk)) {
		ret = PTR_ERR(clk);
		dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret);
		return ret;
	}

	ret = clk_prepare_enable(clk);
	if (ret < 0) {
		dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n",
			ret);
		goto err_put;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (!res) {
		dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
		ret = -ENOMEM;
		goto err;
	}

	base = ioremap(res->start, resource_size(res));
	if (!base) {
		dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res);
		ret = -ENOMEM;
		goto err;
	}

	/*
	 * Setup Async configuration register in case we did not boot
	 * from NAND and so bootloader did not bother to set it up.
	 */
	val = davinci_aemif_readl(base, A1CR_OFFSET + pdata->core_chipsel * 4);
	/*
	 * Extended Wait is not valid and Select Strobe mode is not
	 * used
	 */
	val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
	if (pdata->options & NAND_BUSWIDTH_16)
		val |= 0x1;

	davinci_aemif_writel(base, A1CR_OFFSET + pdata->core_chipsel * 4, val);

	clkrate = clk_get_rate(clk);

	if (pdata->timing)
		ret = davinci_aemif_setup_timing(pdata->timing, base,
						 pdata->core_chipsel, clkrate);

	if (ret < 0)
		dev_dbg(&pdev->dev, "NAND timing values setup fail\n");

	iounmap(base);
err:
	clk_disable_unprepare(clk);
err_put:
	clk_put(clk);
	return ret;
}
+48 −20
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/platform_data/mtd-davinci-aemif.h>
#include <linux/platform_data/spi-davinci.h>
#include <linux/platform_data/usb-davinci.h>
#include <linux/platform_data/ti-aemif.h>
#include <linux/regulator/machine.h>

#include <asm/mach-types.h>
@@ -110,15 +111,9 @@ static __init void da830_evm_usb_init(void)
{
	int ret;

	/* USB_REFCLKIN is not used. */
	ret = da8xx_register_usb20_phy_clk(false);
	ret = da8xx_register_usb_phy_clocks();
	if (ret)
		pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n",
			__func__, ret);

	ret = da8xx_register_usb11_phy_clk(false);
	if (ret)
		pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n",
		pr_warn("%s: USB PHY CLK registration failed: %d\n",
			__func__, ret);

	ret = da8xx_register_usb_phy();
@@ -339,7 +334,8 @@ static struct resource da830_evm_nand_resources[] = {
	},
};

static struct platform_device da830_evm_nand_device = {
static struct platform_device da830_evm_aemif_devices[] = {
	{
		.name		= "davinci_nand",
		.id		= 1,
		.dev		= {
@@ -347,6 +343,39 @@ static struct platform_device da830_evm_nand_device = {
		},
		.num_resources	= ARRAY_SIZE(da830_evm_nand_resources),
		.resource	= da830_evm_nand_resources,
	},
};

static struct resource da830_evm_aemif_resource[] = {
	{
		.start	= DA8XX_AEMIF_CTL_BASE,
		.end	= DA8XX_AEMIF_CTL_BASE + SZ_32K - 1,
		.flags	= IORESOURCE_MEM,
	},
};

static struct aemif_abus_data da830_evm_aemif_abus_data[] = {
	{
		.cs	= 3,
	},
};

static struct aemif_platform_data da830_evm_aemif_pdata = {
	.abus_data		= da830_evm_aemif_abus_data,
	.num_abus_data		= ARRAY_SIZE(da830_evm_aemif_abus_data),
	.sub_devices		= da830_evm_aemif_devices,
	.num_sub_devices	= ARRAY_SIZE(da830_evm_aemif_devices),
	.cs_offset		= 2,
};

static struct platform_device da830_evm_aemif_device = {
	.name		= "ti-aemif",
	.id		= -1,
	.dev = {
		.platform_data = &da830_evm_aemif_pdata,
	},
	.resource	= da830_evm_aemif_resource,
	.num_resources	= ARRAY_SIZE(da830_evm_aemif_resource),
};

/*
@@ -377,12 +406,9 @@ static inline void da830_evm_init_nand(int mux_mode)
	if (ret)
		pr_warn("%s: emif25 mux setup failed: %d\n", __func__, ret);

	ret = platform_device_register(&da830_evm_nand_device);
	ret = platform_device_register(&da830_evm_aemif_device);
	if (ret)
		pr_warn("%s: NAND device not registered\n", __func__);

	if (davinci_aemif_setup(&da830_evm_nand_device))
		pr_warn("%s: Cannot configure AEMIF\n", __func__);
		pr_warn("%s: AEMIF device not registered\n", __func__);

	gpio_direction_output(mux_mode, 1);
}
@@ -557,6 +583,8 @@ static __init void da830_evm_init(void)
	struct davinci_soc_info *soc_info = &davinci_soc_info;
	int ret;

	da830_register_clocks();

	ret = da830_register_gpio();
	if (ret)
		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
Loading