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

Commit 8c4a57bc authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'davinci-for-v3.15/nand' of...

Merge tag 'davinci-for-v3.15/nand' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci into next/drivers

A patch to break dependency of DaVinci NAND
driver with mach-davinci. Required for reuse
of driver on other platforms (keystone).

* tag 'davinci-for-v3.15/nand' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci

:
  ARM: davinci: aemif: get rid of davinci-nand driver dependency on aemif

Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents b5feaefb 67f5185c
Loading
Loading
Loading
Loading
+96 −11
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/time.h>

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

/* Timing value configuration */

@@ -43,6 +44,17 @@
				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.
@@ -76,6 +88,7 @@ static int aemif_calc_rate(int wanted, unsigned long clk, int max)
 * @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.
@@ -86,24 +99,17 @@ static int aemif_calc_rate(int wanted, unsigned long clk, int max)
 *
 * Returns 0 on success, else negative errno.
 */
int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
					void __iomem *base, unsigned cs)
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;
	struct clk *aemif_clk;
	unsigned long clkrate;

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

	aemif_clk = clk_get(NULL, "aemif");
	if (IS_ERR(aemif_clk))
		return PTR_ERR(aemif_clk);

	clkrate = clk_get_rate(aemif_clk);

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

	ta	= aemif_calc_rate(t->ta, clkrate, TA_MAX);
@@ -130,4 +136,83 @@ int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,

	return 0;
}
EXPORT_SYMBOL(davinci_aemif_setup_timing);

/**
 * 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 + pdev->id * 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 + pdev->id * 4, val);

	clkrate = clk_get_rate(clk);

	if (pdata->timing)
		ret = davinci_aemif_setup_timing(pdata->timing, base, pdev->id,
						 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;
}
+3 −0
Original line number Diff line number Diff line
@@ -419,6 +419,9 @@ static inline void da830_evm_init_nand(int mux_mode)
	if (ret)
		pr_warning("da830_evm_init: NAND device not registered.\n");

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

	gpio_direction_output(mux_mode, 1);
}
#else
+3 −0
Original line number Diff line number Diff line
@@ -358,6 +358,9 @@ static inline void da850_evm_setup_nor_nand(void)

		platform_add_devices(da850_evm_devices,
					ARRAY_SIZE(da850_evm_devices));

		if (davinci_aemif_setup(&da850_evm_nandflash_device))
			pr_warn("%s: Cannot configure AEMIF.\n", __func__);
	}
}

+5 −0
Original line number Diff line number Diff line
@@ -778,6 +778,11 @@ static __init void davinci_evm_init(void)
		/* only one device will be jumpered and detected */
		if (HAS_NAND) {
			platform_device_register(&davinci_evm_nandflash_device);

			if (davinci_aemif_setup(&davinci_evm_nandflash_device))
				pr_warn("%s: Cannot configure AEMIF.\n",
					__func__);

			evm_leds[7].default_trigger = "nand-disk";
			if (HAS_NOR)
				pr_warning("WARNING: both NAND and NOR flash "
+3 −0
Original line number Diff line number Diff line
@@ -805,6 +805,9 @@ static __init void evm_init(void)

	platform_device_register(&davinci_nand_device);

	if (davinci_aemif_setup(&davinci_nand_device))
		pr_warn("%s: Cannot configure AEMIF.\n", __func__);

	dm646x_init_edma(dm646x_edma_rsv);

	if (HAS_ATA)
Loading