arm-soc: device tree conversions, part 2

These continue the device tree work from part 1, this set is for the
 tegra, mxs and imx platforms, all of which have dependencies on clock
 or pinctrl changes submitted earlier.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJPuex7AAoJEIwa5zzehBx3xsQP/jkyt74MvuKUi8pi2zkeMIgn
 4XieyqcA0KZjJzfB22q3GIZjNIf/mEIGE4E/3bneVMPh/E2zaiohaXFExBmjNjml
 hhzWeZlFGPBjrZsfpIXJIIUhwSI7gX2rjYh4npJmdNhZmy8Y89XnpNJhN1kOwMuV
 oN23hPWoSVGbyDMQ0fmHx9GyOL8m7yap+joG13aljDa2OKpQg+pYvdwft+k1K9di
 8yPF+qA043UUR7dSsjmTbiCcjZy2eySdCmfOAkEG4inSgxNoM7GBs3MuwZo/veCD
 v5WssJqWDbLXtqKn5Uo2bvGWiEcf0xtwOAqhSpbaup3dQFJSWMEenBTtA9UlxFhk
 6gdY62O+7k6N0thkxXyLNGkgaGzexZAsK7dM6XSDB+PqD+OSNJS7dvmxZM8tuaRn
 rvCM1XWcNeN/dpnLbgwCR12efkwWtJoqqUZUUp/tFFaTo8HriqeAIYk7obnR8s9n
 S5x9LeueQGNgaxXJzVdh481YKG/1lqjG/a06HbVgYS4XQvtdA+4khalOefJv10tm
 Nkg8+4/8pMthWJfhhlfPUgWFXOXFF2AGPG4su2XwKuFXypO8599lzi7gUQaEZu2U
 7caqoWP69KsKvK5iAAmA4DQ2rcsgHd44NXx/8Jjes9ma8knlYjrf42dBH6AZMQBG
 69I9sJ1cyqusBwx72NPN
 =WeDQ
 -----END PGP SIGNATURE-----

Merge tag 'dt2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull arm-soc device tree conversions (part 2) from Olof Johansson:
 "These continue the device tree work from part 1, this set is for the
  tegra, mxs and imx platforms, all of which have dependencies on clock
  or pinctrl changes submitted earlier."

Fix up trivial conflicts due to nearby changes in
drivers/{gpio/gpio,i2c/busses/i2c}-mxs.c

* tag 'dt2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (73 commits)
  ARM: dt: tegra: invert status=disable vs status=okay
  ARM: dt: tegra: consistent basic property ordering
  ARM: dt: tegra: sort nodes based on bus order
  ARM: dt: tegra: remove duplicate device_type property
  ARM: dt: tegra: consistenly use lower-case for hex constants
  ARM: dt: tegra: format regs properties consistently
  ARM: dt: tegra: gpio comment cleanup
  ARM: dt: tegra: remove unnecessary unit addresses
  ARM: dt: tegra: whitespace cleanup
  ARM: dt: tegra cardhu: fix typo in SDHCI node name
  ARM: dt: tegra: cardhu: register core regulator tps62361
  ARM: dt: tegra30.dtsi: Add SMMU node
  ARM: dt: tegra20.dtsi: Add GART node
  ARM: dt: tegra30.dtsi: Add Memory Controller(MC) nodes
  ARM: dt: tegra20.dtsi: Add Memory Controller(MC) nodes
  ARM: dt: tegra: Add device tree support for AHB
  ARM: dts: enable audio support for imx28-evk
  ARM: dts: enable i2c device for imx28-evk
  i2c: mxs: add device tree probe support
  ARM: dts: enable mmc for imx28-evk
  ...
This commit is contained in:
Linus Torvalds 2012-05-26 12:57:47 -07:00
commit 84a442b9a1
63 changed files with 2972 additions and 987 deletions

View file

@ -238,6 +238,7 @@ config IMX_DMA
config MXS_DMA
bool "MXS DMA support"
depends on SOC_IMX23 || SOC_IMX28
select STMP_DEVICE
select DMA_ENGINE
help
Support the MXS DMA engine. This engine including APBH-DMA

View file

@ -22,11 +22,14 @@
#include <linux/platform_device.h>
#include <linux/dmaengine.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/fsl/mxs-dma.h>
#include <linux/stmp_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <asm/irq.h>
#include <mach/mxs.h>
#include <mach/common.h>
#include "dmaengine.h"
@ -36,12 +39,8 @@
* dma can program the controller registers of peripheral devices.
*/
#define MXS_DMA_APBH 0
#define MXS_DMA_APBX 1
#define dma_is_apbh() (mxs_dma->dev_id == MXS_DMA_APBH)
#define APBH_VERSION_LATEST 3
#define apbh_is_old() (mxs_dma->version < APBH_VERSION_LATEST)
#define dma_is_apbh(mxs_dma) ((mxs_dma)->type == MXS_DMA_APBH)
#define apbh_is_old(mxs_dma) ((mxs_dma)->dev_id == IMX23_DMA)
#define HW_APBHX_CTRL0 0x000
#define BM_APBH_CTRL0_APB_BURST8_EN (1 << 29)
@ -51,13 +50,14 @@
#define HW_APBHX_CTRL2 0x020
#define HW_APBHX_CHANNEL_CTRL 0x030
#define BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL 16
#define HW_APBH_VERSION (cpu_is_mx23() ? 0x3f0 : 0x800)
#define HW_APBX_VERSION 0x800
#define BP_APBHX_VERSION_MAJOR 24
#define HW_APBHX_CHn_NXTCMDAR(n) \
(((dma_is_apbh() && apbh_is_old()) ? 0x050 : 0x110) + (n) * 0x70)
#define HW_APBHX_CHn_SEMA(n) \
(((dma_is_apbh() && apbh_is_old()) ? 0x080 : 0x140) + (n) * 0x70)
/*
* The offset of NXTCMDAR register is different per both dma type and version,
* while stride for each channel is all the same 0x70.
*/
#define HW_APBHX_CHn_NXTCMDAR(d, n) \
(((dma_is_apbh(d) && apbh_is_old(d)) ? 0x050 : 0x110) + (n) * 0x70)
#define HW_APBHX_CHn_SEMA(d, n) \
(((dma_is_apbh(d) && apbh_is_old(d)) ? 0x080 : 0x140) + (n) * 0x70)
/*
* ccw bits definitions
@ -121,9 +121,19 @@ struct mxs_dma_chan {
#define MXS_DMA_CHANNELS 16
#define MXS_DMA_CHANNELS_MASK 0xffff
enum mxs_dma_devtype {
MXS_DMA_APBH,
MXS_DMA_APBX,
};
enum mxs_dma_id {
IMX23_DMA,
IMX28_DMA,
};
struct mxs_dma_engine {
int dev_id;
unsigned int version;
enum mxs_dma_id dev_id;
enum mxs_dma_devtype type;
void __iomem *base;
struct clk *clk;
struct dma_device dma_device;
@ -131,17 +141,86 @@ struct mxs_dma_engine {
struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS];
};
struct mxs_dma_type {
enum mxs_dma_id id;
enum mxs_dma_devtype type;
};
static struct mxs_dma_type mxs_dma_types[] = {
{
.id = IMX23_DMA,
.type = MXS_DMA_APBH,
}, {
.id = IMX23_DMA,
.type = MXS_DMA_APBX,
}, {
.id = IMX28_DMA,
.type = MXS_DMA_APBH,
}, {
.id = IMX28_DMA,
.type = MXS_DMA_APBX,
}
};
static struct platform_device_id mxs_dma_ids[] = {
{
.name = "imx23-dma-apbh",
.driver_data = (kernel_ulong_t) &mxs_dma_types[0],
}, {
.name = "imx23-dma-apbx",
.driver_data = (kernel_ulong_t) &mxs_dma_types[1],
}, {
.name = "imx28-dma-apbh",
.driver_data = (kernel_ulong_t) &mxs_dma_types[2],
}, {
.name = "imx28-dma-apbx",
.driver_data = (kernel_ulong_t) &mxs_dma_types[3],
}, {
/* end of list */
}
};
static const struct of_device_id mxs_dma_dt_ids[] = {
{ .compatible = "fsl,imx23-dma-apbh", .data = &mxs_dma_ids[0], },
{ .compatible = "fsl,imx23-dma-apbx", .data = &mxs_dma_ids[1], },
{ .compatible = "fsl,imx28-dma-apbh", .data = &mxs_dma_ids[2], },
{ .compatible = "fsl,imx28-dma-apbx", .data = &mxs_dma_ids[3], },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mxs_dma_dt_ids);
static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan)
{
return container_of(chan, struct mxs_dma_chan, chan);
}
int mxs_dma_is_apbh(struct dma_chan *chan)
{
struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
return dma_is_apbh(mxs_dma);
}
int mxs_dma_is_apbx(struct dma_chan *chan)
{
struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
return !dma_is_apbh(mxs_dma);
}
static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
{
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
int chan_id = mxs_chan->chan.chan_id;
if (dma_is_apbh() && apbh_is_old())
if (dma_is_apbh(mxs_dma) && apbh_is_old(mxs_dma))
writel(1 << (chan_id + BP_APBH_CTRL0_RESET_CHANNEL),
mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET);
else
writel(1 << (chan_id + BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL),
mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR);
mxs_dma->base + HW_APBHX_CHANNEL_CTRL + STMP_OFFSET_REG_SET);
}
static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
@ -151,10 +230,10 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
/* set cmd_addr up */
writel(mxs_chan->ccw_phys,
mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(mxs_dma, chan_id));
/* write 1 to SEMA to kick off the channel */
writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id));
writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(mxs_dma, chan_id));
}
static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
@ -168,12 +247,12 @@ static void mxs_dma_pause_chan(struct mxs_dma_chan *mxs_chan)
int chan_id = mxs_chan->chan.chan_id;
/* freeze the channel */
if (dma_is_apbh() && apbh_is_old())
if (dma_is_apbh(mxs_dma) && apbh_is_old(mxs_dma))
writel(1 << chan_id,
mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET);
else
writel(1 << chan_id,
mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR);
mxs_dma->base + HW_APBHX_CHANNEL_CTRL + STMP_OFFSET_REG_SET);
mxs_chan->status = DMA_PAUSED;
}
@ -184,21 +263,16 @@ static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan)
int chan_id = mxs_chan->chan.chan_id;
/* unfreeze the channel */
if (dma_is_apbh() && apbh_is_old())
if (dma_is_apbh(mxs_dma) && apbh_is_old(mxs_dma))
writel(1 << chan_id,
mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_CLR);
else
writel(1 << chan_id,
mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_CLR_ADDR);
mxs_dma->base + HW_APBHX_CHANNEL_CTRL + STMP_OFFSET_REG_CLR);
mxs_chan->status = DMA_IN_PROGRESS;
}
static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan)
{
return container_of(chan, struct mxs_dma_chan, chan);
}
static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
{
return dma_cookie_assign(tx);
@ -220,11 +294,11 @@ static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
/* completion status */
stat1 = readl(mxs_dma->base + HW_APBHX_CTRL1);
stat1 &= MXS_DMA_CHANNELS_MASK;
writel(stat1, mxs_dma->base + HW_APBHX_CTRL1 + MXS_CLR_ADDR);
writel(stat1, mxs_dma->base + HW_APBHX_CTRL1 + STMP_OFFSET_REG_CLR);
/* error status */
stat2 = readl(mxs_dma->base + HW_APBHX_CTRL2);
writel(stat2, mxs_dma->base + HW_APBHX_CTRL2 + MXS_CLR_ADDR);
writel(stat2, mxs_dma->base + HW_APBHX_CTRL2 + STMP_OFFSET_REG_CLR);
/*
* When both completion and error of termination bits set at the
@ -567,27 +641,21 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
if (ret)
return ret;
ret = mxs_reset_block(mxs_dma->base);
ret = stmp_reset_block(mxs_dma->base);
if (ret)
goto err_out;
/* only major version matters */
mxs_dma->version = readl(mxs_dma->base +
((mxs_dma->dev_id == MXS_DMA_APBX) ?
HW_APBX_VERSION : HW_APBH_VERSION)) >>
BP_APBHX_VERSION_MAJOR;
/* enable apbh burst */
if (dma_is_apbh()) {
if (dma_is_apbh(mxs_dma)) {
writel(BM_APBH_CTRL0_APB_BURST_EN,
mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET);
writel(BM_APBH_CTRL0_APB_BURST8_EN,
mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET);
}
/* enable irq for all the channels */
writel(MXS_DMA_CHANNELS_MASK << MXS_DMA_CHANNELS,
mxs_dma->base + HW_APBHX_CTRL1 + MXS_SET_ADDR);
mxs_dma->base + HW_APBHX_CTRL1 + STMP_OFFSET_REG_SET);
err_out:
clk_disable_unprepare(mxs_dma->clk);
@ -596,8 +664,9 @@ err_out:
static int __init mxs_dma_probe(struct platform_device *pdev)
{
const struct platform_device_id *id_entry =
platform_get_device_id(pdev);
const struct platform_device_id *id_entry;
const struct of_device_id *of_id;
const struct mxs_dma_type *dma_type;
struct mxs_dma_engine *mxs_dma;
struct resource *iores;
int ret, i;
@ -606,7 +675,15 @@ static int __init mxs_dma_probe(struct platform_device *pdev)
if (!mxs_dma)
return -ENOMEM;
mxs_dma->dev_id = id_entry->driver_data;
of_id = of_match_device(mxs_dma_dt_ids, &pdev->dev);
if (of_id)
id_entry = of_id->data;
else
id_entry = platform_get_device_id(pdev);
dma_type = (struct mxs_dma_type *)id_entry->driver_data;
mxs_dma->type = dma_type->type;
mxs_dma->dev_id = dma_type->id;
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -689,23 +766,12 @@ err_request_region:
return ret;
}
static struct platform_device_id mxs_dma_type[] = {
{
.name = "mxs-dma-apbh",
.driver_data = MXS_DMA_APBH,
}, {
.name = "mxs-dma-apbx",
.driver_data = MXS_DMA_APBX,
}, {
/* end of list */
}
};
static struct platform_driver mxs_dma_driver = {
.driver = {
.name = "mxs-dma",
.of_match_table = mxs_dma_dt_ids,
},
.id_table = mxs_dma_type,
.id_table = mxs_dma_ids,
};
static int __init mxs_dma_module_init(void)