From c4cea7fc1bfd8a36d08f8114efcb11d649d97d5a Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Sun, 22 Apr 2012 11:59:47 +0200 Subject: i2c: pnx: Disable clk in suspend In the driver's suspend function, clk_enable() was used instead of clk_disable(). This is corrected with this patch. Signed-off-by: Roland Stigge Reviewed-by: Arnd Bergmann Signed-off-by: Wolfram Sang CC: stable@vger.kernel.org --- drivers/i2c/busses/i2c-pnx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 04be9f82..eb8ad53 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -546,8 +546,7 @@ static int i2c_pnx_controller_suspend(struct platform_device *pdev, { struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); - /* FIXME: shouldn't this be clk_disable? */ - clk_enable(alg_data->clk); + clk_disable(alg_data->clk); return 0; } -- cgit v1.1 From 1451ba3a5fa52d874e03a3380d053f3e6a5fcae4 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Sun, 22 Apr 2012 11:59:47 +0200 Subject: i2c-pnx.c: Use resources in platforms As a precondition for device tree conversion, the platforms using i2c-pnx.c are converted to using mem and irq resources instead of platform data. Signed-off-by: Roland Stigge Reviewed-by: Arnd Bergmann Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pnx.c | 47 +++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index eb8ad53..6fb97ae 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -568,14 +568,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) int ret = 0; struct i2c_pnx_algo_data *alg_data; unsigned long freq; - struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data; - - if (!i2c_pnx || !i2c_pnx->name) { - dev_err(&pdev->dev, "%s: no platform data supplied\n", - __func__); - ret = -EINVAL; - goto out; - } + struct resource *res; alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL); if (!alg_data) { @@ -585,13 +578,10 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) platform_set_drvdata(pdev, alg_data); - strlcpy(alg_data->adapter.name, i2c_pnx->name, - sizeof(alg_data->adapter.name)); alg_data->adapter.dev.parent = &pdev->dev; alg_data->adapter.algo = &pnx_algorithm; alg_data->adapter.algo_data = alg_data; alg_data->adapter.nr = pdev->id; - alg_data->i2c_pnx = i2c_pnx; alg_data->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(alg_data->clk)) { @@ -603,17 +593,27 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) alg_data->mif.timer.function = i2c_pnx_timeout; alg_data->mif.timer.data = (unsigned long)alg_data; + snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name), + "%s", pdev->name); + /* Register I/O resource */ - if (!request_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE, + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Unable to get mem resource.\n"); + ret = -EBUSY; + goto out_clkget; + } + if (!request_mem_region(res->start, I2C_PNX_REGION_SIZE, pdev->name)) { dev_err(&pdev->dev, "I/O region 0x%08x for I2C already in use.\n", - i2c_pnx->base); + res->start); ret = -ENODEV; goto out_clkget; } - alg_data->ioaddr = ioremap(i2c_pnx->base, I2C_PNX_REGION_SIZE); + alg_data->base = res->start; + alg_data->ioaddr = ioremap(res->start, I2C_PNX_REGION_SIZE); if (!alg_data->ioaddr) { dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n"); ret = -ENOMEM; @@ -650,7 +650,12 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) } init_completion(&alg_data->mif.complete); - ret = request_irq(i2c_pnx->irq, i2c_pnx_interrupt, + alg_data->irq = platform_get_irq(pdev, 0); + if (alg_data->irq < 0) { + dev_err(&pdev->dev, "Failed to get IRQ from platform resource\n"); + goto out_irq; + } + ret = request_irq(alg_data->irq, i2c_pnx_interrupt, 0, pdev->name, alg_data); if (ret) goto out_clock; @@ -663,38 +668,36 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) } dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", - alg_data->adapter.name, i2c_pnx->base, i2c_pnx->irq); + alg_data->adapter.name, res->start, alg_data->irq); return 0; out_irq: - free_irq(i2c_pnx->irq, alg_data); + free_irq(alg_data->irq, alg_data); out_clock: clk_disable(alg_data->clk); out_unmap: iounmap(alg_data->ioaddr); out_release: - release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE); + release_mem_region(res->start, I2C_PNX_REGION_SIZE); out_clkget: clk_put(alg_data->clk); out_drvdata: kfree(alg_data); err_kzalloc: platform_set_drvdata(pdev, NULL); -out: return ret; } static int __devexit i2c_pnx_remove(struct platform_device *pdev) { struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); - struct i2c_pnx_data *i2c_pnx = alg_data->i2c_pnx; - free_irq(i2c_pnx->irq, alg_data); + free_irq(alg_data->irq, alg_data); i2c_del_adapter(&alg_data->adapter); clk_disable(alg_data->clk); iounmap(alg_data->ioaddr); - release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE); + release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE); clk_put(alg_data->clk); kfree(alg_data); platform_set_drvdata(pdev, NULL); -- cgit v1.1 From be460385af1c40905dd6858a475bc949a3072b08 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Sun, 22 Apr 2012 11:59:47 +0200 Subject: i2c-pnx.c: Remove duplicated i2c.h The platforms using i2c-pnx.c both defined a duplicated i2c.h (used nowhere else). This patch removes those and integrates the contents into the driver itself. Signed-off-by: Roland Stigge Reviewed-by: Arnd Bergmann Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pnx.c | 49 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 6fb97ae..f69d80b 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -24,13 +24,56 @@ #include #include -#include -#include - #define I2C_PNX_TIMEOUT 10 /* msec */ #define I2C_PNX_SPEED_KHZ 100 #define I2C_PNX_REGION_SIZE 0x100 +enum { + mstatus_tdi = 0x00000001, + mstatus_afi = 0x00000002, + mstatus_nai = 0x00000004, + mstatus_drmi = 0x00000008, + mstatus_active = 0x00000020, + mstatus_scl = 0x00000040, + mstatus_sda = 0x00000080, + mstatus_rff = 0x00000100, + mstatus_rfe = 0x00000200, + mstatus_tff = 0x00000400, + mstatus_tfe = 0x00000800, +}; + +enum { + mcntrl_tdie = 0x00000001, + mcntrl_afie = 0x00000002, + mcntrl_naie = 0x00000004, + mcntrl_drmie = 0x00000008, + mcntrl_daie = 0x00000020, + mcntrl_rffie = 0x00000040, + mcntrl_tffie = 0x00000080, + mcntrl_reset = 0x00000100, + mcntrl_cdbmode = 0x00000400, +}; + +enum { + rw_bit = 1 << 0, + start_bit = 1 << 8, + stop_bit = 1 << 9, +}; + +#define I2C_REG_RX(a) ((a)->ioaddr) /* Rx FIFO reg (RO) */ +#define I2C_REG_TX(a) ((a)->ioaddr) /* Tx FIFO reg (WO) */ +#define I2C_REG_STS(a) ((a)->ioaddr + 0x04) /* Status reg (RO) */ +#define I2C_REG_CTL(a) ((a)->ioaddr + 0x08) /* Ctl reg */ +#define I2C_REG_CKL(a) ((a)->ioaddr + 0x0c) /* Clock divider low */ +#define I2C_REG_CKH(a) ((a)->ioaddr + 0x10) /* Clock divider high */ +#define I2C_REG_ADR(a) ((a)->ioaddr + 0x14) /* I2C address */ +#define I2C_REG_RFL(a) ((a)->ioaddr + 0x18) /* Rx FIFO level (RO) */ +#define I2C_REG_TFL(a) ((a)->ioaddr + 0x1c) /* Tx FIFO level (RO) */ +#define I2C_REG_RXB(a) ((a)->ioaddr + 0x20) /* Num of bytes Rx-ed (RO) */ +#define I2C_REG_TXB(a) ((a)->ioaddr + 0x24) /* Num of bytes Tx-ed (RO) */ +#define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */ +#define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */ + static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data) { while (timeout > 0 && -- cgit v1.1 From b41a216dafe4dd23c95cb4203de288f773a097a6 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Sun, 22 Apr 2012 11:59:47 +0200 Subject: i2c: Add device tree support to i2c-pnx.c This patch adds device tree support to the pnx-i2c driver by using platform resources for memory region and irq and removing dependency on mach includes. The following platforms are affected: * PNX * LPC31xx (WIP) * LPC32xx The patch is based on a patch by Jon Smirl, working on lpc31xx integration Signed-off-by: Roland Stigge Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pnx.c | 63 +++++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index f69d80b..99389d2 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -23,10 +23,11 @@ #include #include #include +#include -#define I2C_PNX_TIMEOUT 10 /* msec */ -#define I2C_PNX_SPEED_KHZ 100 -#define I2C_PNX_REGION_SIZE 0x100 +#define I2C_PNX_TIMEOUT_DEFAULT 10 /* msec */ +#define I2C_PNX_SPEED_KHZ_DEFAULT 100 +#define I2C_PNX_REGION_SIZE 0x100 enum { mstatus_tdi = 0x00000001, @@ -74,8 +75,9 @@ enum { #define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */ #define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */ -static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data) +static inline int wait_timeout(struct i2c_pnx_algo_data *data) { + long timeout = data->timeout; while (timeout > 0 && (ioread32(I2C_REG_STS(data)) & mstatus_active)) { mdelay(1); @@ -84,8 +86,9 @@ static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data) return (timeout <= 0); } -static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data) +static inline int wait_reset(struct i2c_pnx_algo_data *data) { + long timeout = data->timeout; while (timeout > 0 && (ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) { mdelay(1); @@ -97,7 +100,7 @@ static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data) static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data) { struct timer_list *timer = &alg_data->mif.timer; - unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT); + unsigned long expires = msecs_to_jiffies(alg_data->timeout); if (expires <= 1) expires = 2; @@ -135,7 +138,7 @@ static int i2c_pnx_start(unsigned char slave_addr, } /* First, make sure bus is idle */ - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) { + if (wait_timeout(alg_data)) { /* Somebody else is monopolizing the bus */ dev_err(&alg_data->adapter.dev, "%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n", @@ -228,7 +231,7 @@ static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data) if (alg_data->mif.len == 0) { if (alg_data->last) { /* Wait until the STOP is seen. */ - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) + if (wait_timeout(alg_data)) dev_err(&alg_data->adapter.dev, "The bus is still active after timeout\n"); } @@ -326,7 +329,7 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data) if (alg_data->mif.len == 0) { if (alg_data->last) /* Wait until the STOP is seen. */ - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) + if (wait_timeout(alg_data)) dev_err(&alg_data->adapter.dev, "The bus is still active after timeout\n"); @@ -442,7 +445,7 @@ static void i2c_pnx_timeout(unsigned long data) ctl |= mcntrl_reset; iowrite32(ctl, I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); + wait_reset(alg_data); alg_data->mif.ret = -EIO; complete(&alg_data->mif.complete); } @@ -457,18 +460,18 @@ static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data) alg_data->adapter.name); iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); + wait_reset(alg_data); } else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) { /* If there is data in the fifo's after transfer, * flush fifo's by reset. */ iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); + wait_reset(alg_data); } else if (stat & mstatus_nai) { iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); + wait_reset(alg_data); } } @@ -612,6 +615,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) struct i2c_pnx_algo_data *alg_data; unsigned long freq; struct resource *res; + u32 speed = I2C_PNX_SPEED_KHZ_DEFAULT * 1000; alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL); if (!alg_data) { @@ -626,6 +630,22 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) alg_data->adapter.algo_data = alg_data; alg_data->adapter.nr = pdev->id; + alg_data->timeout = I2C_PNX_TIMEOUT_DEFAULT; +#ifdef CONFIG_OF + alg_data->adapter.dev.of_node = of_node_get(pdev->dev.of_node); + if (pdev->dev.of_node) { + of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &speed); + /* + * At this point, it is planned to add an OF timeout property. + * As soon as there is a consensus about how to call and handle + * this, sth. like the following can be put here: + * + * of_property_read_u32(pdev->dev.of_node, "timeout", + * &alg_data->timeout); + */ + } +#endif alg_data->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(alg_data->clk)) { ret = PTR_ERR(alg_data->clk); @@ -651,7 +671,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) dev_err(&pdev->dev, "I/O region 0x%08x for I2C already in use.\n", res->start); - ret = -ENODEV; + ret = -ENOMEM; goto out_clkget; } @@ -680,14 +700,14 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) * the deglitching filter length. */ - tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2; + tmp = (freq / speed) / 2 - 2; if (tmp > 0x3FF) tmp = 0x3FF; iowrite32(tmp, I2C_REG_CKH(alg_data)); iowrite32(tmp, I2C_REG_CKL(alg_data)); iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data)); - if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) { + if (wait_reset(alg_data)) { ret = -ENODEV; goto out_clock; } @@ -710,6 +730,8 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) goto out_irq; } + of_i2c_register_devices(&alg_data->adapter); + dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", alg_data->adapter.name, res->start, alg_data->irq); @@ -748,10 +770,19 @@ static int __devexit i2c_pnx_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id i2c_pnx_of_match[] = { + { .compatible = "nxp,pnx-i2c" }, + { }, +}; +MODULE_DEVICE_TABLE(of, i2c_pnx_of_match); +#endif + static struct platform_driver i2c_pnx_driver = { .driver = { .name = "pnx-i2c", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(i2c_pnx_of_match), }, .probe = i2c_pnx_probe, .remove = __devexit_p(i2c_pnx_remove), -- cgit v1.1 From 4de02e4a280678224bd12ec3b182e369c87c8fc5 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Sun, 22 Apr 2012 12:01:19 +0200 Subject: net: Add device tree support to LPC32xx This patch adds device tree support for lpc_eth.c. The runtime option for MII/RMII is solved via the "phy-mode" property, SRAM ("IRAM") usage for DMA can be chosen via "use-iram". Signed-off-by: Roland Stigge Reviewed-by: Arnd Bergmann Acked-by: David S. Miller --- drivers/net/ethernet/nxp/lpc_eth.c | 71 +++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 6dfc26d..52deec0 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -340,13 +341,17 @@ */ #define LPC_POWERDOWN_MACAHB (1 << 31) -/* Upon the upcoming introduction of device tree usage in LPC32xx, - * lpc_phy_interface_mode() and use_iram_for_net() will be extended with a - * device parameter for access to device tree information at runtime, instead - * of defining the values at compile time - */ -static inline phy_interface_t lpc_phy_interface_mode(void) +static phy_interface_t lpc_phy_interface_mode(struct device *dev) { + if (dev && dev->of_node) { + const char *mode = of_get_property(dev->of_node, + "phy-mode", NULL); + if (mode && !strcmp(mode, "mii")) + return PHY_INTERFACE_MODE_MII; + return PHY_INTERFACE_MODE_RMII; + } + + /* non-DT */ #ifdef CONFIG_ARCH_LPC32XX_MII_SUPPORT return PHY_INTERFACE_MODE_MII; #else @@ -354,12 +359,16 @@ static inline phy_interface_t lpc_phy_interface_mode(void) #endif } -static inline int use_iram_for_net(void) +static bool use_iram_for_net(struct device *dev) { + if (dev && dev->of_node) + return of_property_read_bool(dev->of_node, "use-iram"); + + /* non-DT */ #ifdef CONFIG_ARCH_LPC32XX_IRAM_FOR_NET - return 1; + return true; #else - return 0; + return false; #endif } @@ -664,7 +673,7 @@ static void __lpc_eth_init(struct netdata_local *pldat) LPC_ENET_CLRT(pldat->net_base)); writel(LPC_IPGR_LOAD_PART2(0x12), LPC_ENET_IPGR(pldat->net_base)); - if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII) + if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII) writel(LPC_COMMAND_PASSRUNTFRAME, LPC_ENET_COMMAND(pldat->net_base)); else { @@ -804,12 +813,13 @@ static int lpc_mii_probe(struct net_device *ndev) } /* Attach to the PHY */ - if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII) + if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII) netdev_info(ndev, "using MII interface\n"); else netdev_info(ndev, "using RMII interface\n"); phydev = phy_connect(ndev, dev_name(&phydev->dev), - &lpc_handle_link_change, 0, lpc_phy_interface_mode()); + &lpc_handle_link_change, 0, + lpc_phy_interface_mode(&pldat->pdev->dev)); if (IS_ERR(phydev)) { netdev_err(ndev, "Could not attach to PHY\n"); @@ -843,7 +853,7 @@ static int lpc_mii_init(struct netdata_local *pldat) } /* Setup MII mode */ - if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII) + if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII) writel(LPC_COMMAND_PASSRUNTFRAME, LPC_ENET_COMMAND(pldat->net_base)); else { @@ -1315,18 +1325,26 @@ static const struct net_device_ops lpc_netdev_ops = { static int lpc_eth_drv_probe(struct platform_device *pdev) { struct resource *res; - struct resource *dma_res; struct net_device *ndev; struct netdata_local *pldat; struct phy_device *phydev; dma_addr_t dma_handle; int irq, ret; + u32 tmp; + + /* Setup network interface for RMII or MII mode */ + tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL); + tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK; + if (lpc_phy_interface_mode(&pdev->dev) == PHY_INTERFACE_MODE_MII) + tmp |= LPC32XX_CLKPWR_MACCTRL_USE_MII_PINS; + else + tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS; + __raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL); /* Get platform resources */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); irq = platform_get_irq(pdev, 0); - if ((!res) || (!dma_res) || (irq < 0) || (irq >= NR_IRQS)) { + if ((!res) || (irq < 0) || (irq >= NR_IRQS)) { dev_err(&pdev->dev, "error getting resources.\n"); ret = -ENXIO; goto err_exit; @@ -1389,17 +1407,19 @@ static int lpc_eth_drv_probe(struct platform_device *pdev) sizeof(struct txrx_desc_t) + sizeof(struct rx_status_t)); pldat->dma_buff_base_v = 0; - if (use_iram_for_net()) { - dma_handle = dma_res->start; + if (use_iram_for_net(&pldat->pdev->dev)) { + dma_handle = LPC32XX_IRAM_BASE; if (pldat->dma_buff_size <= lpc32xx_return_iram_size()) pldat->dma_buff_base_v = - io_p2v(dma_res->start); + io_p2v(LPC32XX_IRAM_BASE); else netdev_err(ndev, "IRAM not big enough for net buffers, using SDRAM instead.\n"); } if (pldat->dma_buff_base_v == 0) { + pldat->pdev->dev.coherent_dma_mask = 0xFFFFFFFF; + pldat->pdev->dev.dma_mask = &pldat->pdev->dev.coherent_dma_mask; pldat->dma_buff_size = PAGE_ALIGN(pldat->dma_buff_size); /* Allocate a chunk of memory for the DMA ethernet buffers @@ -1488,7 +1508,7 @@ err_out_unregister_netdev: platform_set_drvdata(pdev, NULL); unregister_netdev(ndev); err_out_dma_unmap: - if (!use_iram_for_net() || + if (!use_iram_for_net(&pldat->pdev->dev) || pldat->dma_buff_size > lpc32xx_return_iram_size()) dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size, pldat->dma_buff_base_v, @@ -1515,7 +1535,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev) unregister_netdev(ndev); platform_set_drvdata(pdev, NULL); - if (!use_iram_for_net() || + if (!use_iram_for_net(&pldat->pdev->dev) || pldat->dma_buff_size > lpc32xx_return_iram_size()) dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size, pldat->dma_buff_base_v, @@ -1584,6 +1604,14 @@ static int lpc_eth_drv_resume(struct platform_device *pdev) } #endif +#ifdef CONFIG_OF +static const struct of_device_id lpc_eth_match[] = { + { .compatible = "nxp,lpc-eth" }, + { } +}; +MODULE_DEVICE_TABLE(of, lpc_eth_match); +#endif + static struct platform_driver lpc_eth_driver = { .probe = lpc_eth_drv_probe, .remove = __devexit_p(lpc_eth_drv_remove), @@ -1593,6 +1621,7 @@ static struct platform_driver lpc_eth_driver = { #endif .driver = { .name = MODNAME, + .of_match_table = of_match_ptr(lpc_eth_match), }, }; -- cgit v1.1 From 5019f0b1345b8f6a8e8a0c7c2f89d4a31819a317 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 11 Apr 2012 17:30:11 +0000 Subject: ARM: spear: remove most mach/*.h header contents The register and irq definitions in mach/*.h for spear3xx and spear6xx are now mostly obsolete, after the platforms have been converted to device tree based probing and the data is now part of the device tree files. The misc_regs.h contents are moved into clock.c because that is the only user, aside from the DMA_CHN_CFG that should eventually get handled differently. Some of the contents of mach/spear.h still remain, because they are used to set up the static map table, timer, uart and auxdata tables, but almost everything got removed. We might remove everything but the map table as the DT conversion completes, but that is not a priority. I've also made sure to make both copies of spear.h more or less identical so we can eventually combine them. The spear3?0.h files were only used by the spear3?0.c files, so I merged the contents in there and removed the bits that were unused. This is something that should still be looked at. Signed-off-by: Arnd Bergmann Acked-by: Viresh Kumar --- drivers/of/address.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/of/address.c b/drivers/of/address.c index 66d96f1..7e262a6 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -1,4 +1,5 @@ +#include #include #include #include -- cgit v1.1 From 7a4d5079baf205f39efa0d9a1b273812c15a93aa Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Fri, 13 Apr 2012 15:15:45 +0800 Subject: gpio: pxa: parse gpio from DTS file Parse GPIO numbers from DTS file. Allocate interrupt according to GPIO numbers. Signed-off-by: Haojian Zhuang Acked-by: Arnd Bergmann --- drivers/gpio/gpio-pxa.c | 116 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index fc3ace3..58a6a63 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -11,13 +11,17 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include #include #include #include +#include #include +#include +#include #include #include #include @@ -56,6 +60,10 @@ int pxa_last_gpio; +#ifdef CONFIG_OF +static struct irq_domain *domain; +#endif + struct pxa_gpio_chip { struct gpio_chip chip; void __iomem *regbase; @@ -81,7 +89,6 @@ enum { PXA3XX_GPIO, PXA93X_GPIO, MMP_GPIO = 0x10, - MMP2_GPIO, }; static DEFINE_SPINLOCK(gpio_lock); @@ -475,22 +482,92 @@ static int pxa_gpio_nums(void) gpio_type = MMP_GPIO; } else if (cpu_is_mmp2()) { count = 191; - gpio_type = MMP2_GPIO; + gpio_type = MMP_GPIO; } #endif /* CONFIG_ARCH_MMP */ return count; } +static struct of_device_id pxa_gpio_dt_ids[] = { + { .compatible = "mrvl,pxa-gpio" }, + { .compatible = "mrvl,mmp-gpio", .data = (void *)MMP_GPIO }, + {} +}; + +static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, + handle_edge_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + return 0; +} + +const struct irq_domain_ops pxa_irq_domain_ops = { + .map = pxa_irq_domain_map, +}; + +#ifdef CONFIG_OF +static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev) +{ + int ret, nr_banks, nr_gpios, irq_base; + struct device_node *prev, *next, *np = pdev->dev.of_node; + const struct of_device_id *of_id = + of_match_device(pxa_gpio_dt_ids, &pdev->dev); + + if (!of_id) { + dev_err(&pdev->dev, "Failed to find gpio controller\n"); + return -EFAULT; + } + gpio_type = (int)of_id->data; + + next = of_get_next_child(np, NULL); + prev = next; + if (!next) { + dev_err(&pdev->dev, "Failed to find child gpio node\n"); + ret = -EINVAL; + goto err; + } + for (nr_banks = 1; ; nr_banks++) { + next = of_get_next_child(np, prev); + if (!next) + break; + prev = next; + } + of_node_put(prev); + nr_gpios = nr_banks << 5; + pxa_last_gpio = nr_gpios - 1; + + irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0); + if (irq_base < 0) { + dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); + goto err; + } + domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0, + &pxa_irq_domain_ops, NULL); + return 0; +err: + iounmap(gpio_reg_base); + return ret; +} +#else +#define pxa_gpio_probe_dt(pdev) (-1) +#endif + static int __devinit pxa_gpio_probe(struct platform_device *pdev) { struct pxa_gpio_chip *c; struct resource *res; struct clk *clk; struct pxa_gpio_platform_data *info; - int gpio, irq, ret; + int gpio, irq, ret, use_of = 0; int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; - pxa_last_gpio = pxa_gpio_nums(); + ret = pxa_gpio_probe_dt(pdev); + if (ret < 0) + pxa_last_gpio = pxa_gpio_nums(); + else + use_of = 1; if (!pxa_last_gpio) return -EINVAL; @@ -545,25 +622,27 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev) writel_relaxed(~0, c->regbase + ED_MASK_OFFSET); } + if (!use_of) { #ifdef CONFIG_ARCH_PXA - irq = gpio_to_irq(0); - irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, - handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler); - - irq = gpio_to_irq(1); - irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, - handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); -#endif + irq = gpio_to_irq(0); + irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, + handle_edge_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler); - for (irq = gpio_to_irq(gpio_offset); - irq <= gpio_to_irq(pxa_last_gpio); irq++) { + irq = gpio_to_irq(1); irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); +#endif + + for (irq = gpio_to_irq(gpio_offset); + irq <= gpio_to_irq(pxa_last_gpio); irq++) { + irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, + handle_edge_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } } irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler); @@ -574,6 +653,7 @@ static struct platform_driver pxa_gpio_driver = { .probe = pxa_gpio_probe, .driver = { .name = "pxa-gpio", + .of_match_table = pxa_gpio_dt_ids, }, }; -- cgit v1.1