diff options
Diffstat (limited to 'drivers')
25 files changed, 1518 insertions, 313 deletions
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 2394e9753ef5..725c46162bbd 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -588,12 +588,6 @@ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = { .show_cpu_target = mvebu_sdram_debug_show_orion, }; -/* - * The driver doesn't yet have a DT binding because the details of - * this DT binding still need to be sorted out. However, as a - * preparation, we already use of_device_id to match a SoC description - * string against the SoC specific details of this driver. - */ static const struct of_device_id of_mvebu_mbus_ids[] = { { .compatible = "marvell,armada370-mbus", .data = &armada_370_xp_mbus_data, }, @@ -734,11 +728,11 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base, { const struct of_device_id *of_id; - for (of_id = of_mvebu_mbus_ids; of_id->compatible; of_id++) + for (of_id = of_mvebu_mbus_ids; of_id->compatible[0]; of_id++) if (!strcmp(of_id->compatible, soc)) break; - if (!of_id->compatible) { + if (!of_id->compatible[0]) { pr_err("could not find a matching SoC family\n"); return -ENODEV; } diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index f5e4c21b301f..8cbfcf88fae3 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -119,6 +119,7 @@ static const struct clk_ops icst_ops = { struct clk *icst_clk_register(struct device *dev, const struct clk_icst_desc *desc, + const char *name, void __iomem *base) { struct clk *clk; @@ -130,7 +131,7 @@ struct clk *icst_clk_register(struct device *dev, pr_err("could not allocate ICST clock!\n"); return ERR_PTR(-ENOMEM); } - init.name = "icst"; + init.name = name; init.ops = &icst_ops; init.flags = CLK_IS_ROOT; init.parent_names = NULL; diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h index dad51b6ffd00..be99dd0da785 100644 --- a/drivers/clk/versatile/clk-icst.h +++ b/drivers/clk/versatile/clk-icst.h @@ -15,4 +15,5 @@ struct clk_icst_desc { struct clk *icst_clk_register(struct device *dev, const struct clk_icst_desc *desc, + const char *name, void __iomem *base); diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c index 369139af2a3b..844f8d711a12 100644 --- a/drivers/clk/versatile/clk-impd1.c +++ b/drivers/clk/versatile/clk-impd1.c @@ -1,6 +1,6 @@ /* * Clock driver for the ARM Integrator/IM-PD1 board - * Copyright (C) 2012 Linus Walleij + * Copyright (C) 2012-2013 Linus Walleij * * 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 @@ -18,20 +18,28 @@ #include "clk-icst.h" struct impd1_clk { - struct clk *vcoclk; + char *vco1name; + struct clk *vco1clk; + char *vco2name; + struct clk *vco2clk; + struct clk *mmciclk; + char *uartname; struct clk *uartclk; - struct clk_lookup *clks[3]; + char *spiname; + struct clk *spiclk; + char *scname; + struct clk *scclk; + struct clk_lookup *clks[6]; }; +/* One entry for each connected IM-PD1 LM */ static struct impd1_clk impd1_clks[4]; /* - * There are two VCO's on the IM-PD1 but only one is used by the - * kernel, that is why we are only implementing the control of - * IMPD1_OSC1 here. + * There are two VCO's on the IM-PD1 */ -static const struct icst_params impd1_vco_params = { +static const struct icst_params impd1_vco1_params = { .ref = 24000000, /* 24 MHz */ .vco_max = ICST525_VCO_MAX_3V, .vco_min = ICST525_VCO_MIN, @@ -44,11 +52,29 @@ static const struct icst_params impd1_vco_params = { }; static const struct clk_icst_desc impd1_icst1_desc = { - .params = &impd1_vco_params, + .params = &impd1_vco1_params, .vco_offset = IMPD1_OSC1, .lock_offset = IMPD1_LOCK, }; +static const struct icst_params impd1_vco2_params = { + .ref = 24000000, /* 24 MHz */ + .vco_max = ICST525_VCO_MAX_3V, + .vco_min = ICST525_VCO_MIN, + .vd_min = 12, + .vd_max = 519, + .rd_min = 3, + .rd_max = 120, + .s2div = icst525_s2div, + .idx2s = icst525_idx2s, +}; + +static const struct clk_icst_desc impd1_icst2_desc = { + .params = &impd1_vco2_params, + .vco_offset = IMPD1_OSC2, + .lock_offset = IMPD1_LOCK, +}; + /** * integrator_impd1_clk_init() - set up the integrator clock tree * @base: base address of the logic module (LM) @@ -66,16 +92,39 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id) } imc = &impd1_clks[id]; - clk = icst_clk_register(NULL, &impd1_icst1_desc, base); - imc->vcoclk = clk; + imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id); + clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, base); + imc->vco1clk = clk; imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id); - /* UART reference clock */ - clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT, - 14745600); + /* VCO2 is also called "CLK2" */ + imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id); + clk = icst_clk_register(NULL, &impd1_icst2_desc, imc->vco2name, base); + imc->vco2clk = clk; + + /* MMCI uses CLK2 right off */ + imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00700", id); + + /* UART reference clock divides CLK2 by a fixed factor 4 */ + imc->uartname = kasprintf(GFP_KERNEL, "lm%x-uartclk", id); + clk = clk_register_fixed_factor(NULL, imc->uartname, imc->vco2name, + CLK_IGNORE_UNUSED, 1, 4); imc->uartclk = clk; - imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00100", id); - imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00200", id); + imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00100", id); + imc->clks[3] = clkdev_alloc(clk, NULL, "lm%x:00200", id); + + /* SPI PL022 clock divides CLK2 by a fixed factor 64 */ + imc->spiname = kasprintf(GFP_KERNEL, "lm%x-spiclk", id); + clk = clk_register_fixed_factor(NULL, imc->spiname, imc->vco2name, + CLK_IGNORE_UNUSED, 1, 64); + imc->clks[4] = clkdev_alloc(clk, NULL, "lm%x:00300", id); + + /* Smart Card clock divides CLK2 by a fixed factor 4 */ + imc->scname = kasprintf(GFP_KERNEL, "lm%x-scclk", id); + clk = clk_register_fixed_factor(NULL, imc->scname, imc->vco2name, + CLK_IGNORE_UNUSED, 1, 4); + imc->scclk = clk; + imc->clks[5] = clkdev_alloc(clk, NULL, "lm%x:00600", id); for (i = 0; i < ARRAY_SIZE(imc->clks); i++) clkdev_add(imc->clks[i]); @@ -92,6 +141,13 @@ void integrator_impd1_clk_exit(unsigned int id) for (i = 0; i < ARRAY_SIZE(imc->clks); i++) clkdev_drop(imc->clks[i]); + clk_unregister(imc->spiclk); clk_unregister(imc->uartclk); - clk_unregister(imc->vcoclk); + clk_unregister(imc->vco2clk); + clk_unregister(imc->vco1clk); + kfree(imc->scname); + kfree(imc->spiname); + kfree(imc->uartname); + kfree(imc->vco2name); + kfree(imc->vco1name); } diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-integrator.c index 08593b4ee2c9..bda8967e09c2 100644 --- a/drivers/clk/versatile/clk-integrator.c +++ b/drivers/clk/versatile/clk-integrator.c @@ -78,7 +78,7 @@ void __init integrator_clk_init(bool is_cp) clk_register_clkdev(clk, NULL, "sp804"); /* ICST VCO clock used on the Integrator/CP CLCD */ - clk = icst_clk_register(NULL, &cp_icst_desc, + clk = icst_clk_register(NULL, &cp_icst_desc, "icst", __io_address(INTEGRATOR_HDR_BASE)); clk_register_clkdev(clk, NULL, "clcd"); } diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c index cda07e70a408..747e7b31117c 100644 --- a/drivers/clk/versatile/clk-realview.c +++ b/drivers/clk/versatile/clk-realview.c @@ -84,9 +84,11 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176) /* ICST VCO clock */ if (is_pb1176) - clk = icst_clk_register(NULL, &realview_osc0_desc, sysbase); + clk = icst_clk_register(NULL, &realview_osc0_desc, + "osc0", sysbase); else - clk = icst_clk_register(NULL, &realview_osc4_desc, sysbase); + clk = icst_clk_register(NULL, &realview_osc4_desc, + "osc4", sysbase); clk_register_clkdev(clk, NULL, "dev:clcd"); clk_register_clkdev(clk, NULL, "issp:clcd"); diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index c1efd910d97b..d7c9e317423c 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -30,6 +30,7 @@ #include <linux/irq.h> #include <linux/scatterlist.h> #include <linux/dma-mapping.h> +#include <linux/of_device.h> #include <linux/delay.h> #include <linux/crypto.h> #include <linux/cryptohash.h> @@ -39,6 +40,7 @@ #include <crypto/hash.h> #include <crypto/internal/hash.h> #include <linux/platform_data/crypto-atmel.h> +#include <dt-bindings/dma/at91.h> #include "atmel-aes-regs.h" #define CFB8_BLOCK_SIZE 1 @@ -747,59 +749,50 @@ static int atmel_aes_dma_init(struct atmel_aes_dev *dd, struct crypto_platform_data *pdata) { int err = -ENOMEM; - dma_cap_mask_t mask_in, mask_out; + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* Try to grab 2 DMA channels */ + dd->dma_lch_in.chan = dma_request_slave_channel_compat(mask, + atmel_aes_filter, &pdata->dma_slave->rxdata, dd->dev, "tx"); + if (!dd->dma_lch_in.chan) + goto err_dma_in; + + dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; + dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + + AES_IDATAR(0); + dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size; + dd->dma_lch_in.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size; + dd->dma_lch_in.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.device_fc = false; + + dd->dma_lch_out.chan = dma_request_slave_channel_compat(mask, + atmel_aes_filter, &pdata->dma_slave->txdata, dd->dev, "rx"); + if (!dd->dma_lch_out.chan) + goto err_dma_out; + + dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; + dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + + AES_ODATAR(0); + dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size; + dd->dma_lch_out.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size; + dd->dma_lch_out.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_out.dma_conf.device_fc = false; - if (pdata && pdata->dma_slave->txdata.dma_dev && - pdata->dma_slave->rxdata.dma_dev) { - - /* Try to grab 2 DMA channels */ - dma_cap_zero(mask_in); - dma_cap_set(DMA_SLAVE, mask_in); - - dd->dma_lch_in.chan = dma_request_channel(mask_in, - atmel_aes_filter, &pdata->dma_slave->rxdata); - - if (!dd->dma_lch_in.chan) - goto err_dma_in; - - dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; - dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + - AES_IDATAR(0); - dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size; - dd->dma_lch_in.dma_conf.src_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size; - dd->dma_lch_in.dma_conf.dst_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.device_fc = false; - - dma_cap_zero(mask_out); - dma_cap_set(DMA_SLAVE, mask_out); - dd->dma_lch_out.chan = dma_request_channel(mask_out, - atmel_aes_filter, &pdata->dma_slave->txdata); - - if (!dd->dma_lch_out.chan) - goto err_dma_out; - - dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; - dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + - AES_ODATAR(0); - dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size; - dd->dma_lch_out.dma_conf.src_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size; - dd->dma_lch_out.dma_conf.dst_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_out.dma_conf.device_fc = false; - - return 0; - } else { - return -ENODEV; - } + return 0; err_dma_out: dma_release_channel(dd->dma_lch_in.chan); err_dma_in: + dev_warn(dd->dev, "no DMA channel available\n"); return err; } @@ -1261,6 +1254,47 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd) } } +#if defined(CONFIG_OF) +static const struct of_device_id atmel_aes_dt_ids[] = { + { .compatible = "atmel,at91sam9g46-aes" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, atmel_aes_dt_ids); + +static struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct crypto_platform_data *pdata; + + if (!np) { + dev_err(&pdev->dev, "device node not found\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&pdev->dev, "could not allocate memory for pdata\n"); + return ERR_PTR(-ENOMEM); + } + + pdata->dma_slave = devm_kzalloc(&pdev->dev, + sizeof(*(pdata->dma_slave)), + GFP_KERNEL); + if (!pdata->dma_slave) { + dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); + devm_kfree(&pdev->dev, pdata); + return ERR_PTR(-ENOMEM); + } + + return pdata; +} +#else +static inline struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev) +{ + return ERR_PTR(-EINVAL); +} +#endif + static int atmel_aes_probe(struct platform_device *pdev) { struct atmel_aes_dev *aes_dd; @@ -1272,6 +1306,14 @@ static int atmel_aes_probe(struct platform_device *pdev) pdata = pdev->dev.platform_data; if (!pdata) { + pdata = atmel_aes_of_init(pdev); + if (IS_ERR(pdata)) { + err = PTR_ERR(pdata); + goto aes_dd_err; + } + } + + if (!pdata->dma_slave) { err = -ENXIO; goto aes_dd_err; } @@ -1358,7 +1400,9 @@ static int atmel_aes_probe(struct platform_device *pdev) if (err) goto err_algs; - dev_info(dev, "Atmel AES\n"); + dev_info(dev, "Atmel AES - Using %s, %s for DMA transfers\n", + dma_chan_name(aes_dd->dma_lch_in.chan), + dma_chan_name(aes_dd->dma_lch_out.chan)); return 0; @@ -1424,6 +1468,7 @@ static struct platform_driver atmel_aes_driver = { .driver = { .name = "atmel_aes", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(atmel_aes_dt_ids), }, }; diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index eaed8bf183bc..0618be06b9fb 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -30,6 +30,7 @@ #include <linux/irq.h> #include <linux/scatterlist.h> #include <linux/dma-mapping.h> +#include <linux/of_device.h> #include <linux/delay.h> #include <linux/crypto.h> #include <linux/cryptohash.h> @@ -1263,32 +1264,29 @@ static int atmel_sha_dma_init(struct atmel_sha_dev *dd, int err = -ENOMEM; dma_cap_mask_t mask_in; - if (pdata && pdata->dma_slave->rxdata.dma_dev) { - /* Try to grab DMA channel */ - dma_cap_zero(mask_in); - dma_cap_set(DMA_SLAVE, mask_in); + /* Try to grab DMA channel */ + dma_cap_zero(mask_in); + dma_cap_set(DMA_SLAVE, mask_in); - dd->dma_lch_in.chan = dma_request_channel(mask_in, - atmel_sha_filter, &pdata->dma_slave->rxdata); - - if (!dd->dma_lch_in.chan) - return err; - - dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; - dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + - SHA_REG_DIN(0); - dd->dma_lch_in.dma_conf.src_maxburst = 1; - dd->dma_lch_in.dma_conf.src_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.dst_maxburst = 1; - dd->dma_lch_in.dma_conf.dst_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.device_fc = false; - - return 0; + dd->dma_lch_in.chan = dma_request_slave_channel_compat(mask_in, + atmel_sha_filter, &pdata->dma_slave->rxdata, dd->dev, "tx"); + if (!dd->dma_lch_in.chan) { + dev_warn(dd->dev, "no DMA channel available\n"); + return err; } - return -ENODEV; + dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; + dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + + SHA_REG_DIN(0); + dd->dma_lch_in.dma_conf.src_maxburst = 1; + dd->dma_lch_in.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.dst_maxburst = 1; + dd->dma_lch_in.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.device_fc = false; + + return 0; } static void atmel_sha_dma_cleanup(struct atmel_sha_dev *dd) @@ -1326,6 +1324,48 @@ static void atmel_sha_get_cap(struct atmel_sha_dev *dd) } } +#if defined(CONFIG_OF) +static const struct of_device_id atmel_sha_dt_ids[] = { + { .compatible = "atmel,at91sam9g46-sha" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, atmel_sha_dt_ids); + +static struct crypto_platform_data *atmel_sha_of_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct crypto_platform_data *pdata; + + if (!np) { + dev_err(&pdev->dev, "device node not found\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&pdev->dev, "could not allocate memory for pdata\n"); + return ERR_PTR(-ENOMEM); + } + + pdata->dma_slave = devm_kzalloc(&pdev->dev, + sizeof(*(pdata->dma_slave)), + GFP_KERNEL); + if (!pdata->dma_slave) { + dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); + devm_kfree(&pdev->dev, pdata); + return ERR_PTR(-ENOMEM); + } + + return pdata; +} +#else /* CONFIG_OF */ +static inline struct crypto_platform_data *atmel_sha_of_init(struct platform_device *dev) +{ + return ERR_PTR(-EINVAL); +} +#endif + static int atmel_sha_probe(struct platform_device *pdev) { struct atmel_sha_dev *sha_dd; @@ -1402,13 +1442,23 @@ static int atmel_sha_probe(struct platform_device *pdev) if (sha_dd->caps.has_dma) { pdata = pdev->dev.platform_data; if (!pdata) { - dev_err(&pdev->dev, "platform data not available\n"); + pdata = atmel_sha_of_init(pdev); + if (IS_ERR(pdata)) { + dev_err(&pdev->dev, "platform data not available\n"); + err = PTR_ERR(pdata); + goto err_pdata; + } + } + if (!pdata->dma_slave) { err = -ENXIO; goto err_pdata; } err = atmel_sha_dma_init(sha_dd, pdata); if (err) goto err_sha_dma; + + dev_info(dev, "using %s for DMA transfers\n", + dma_chan_name(sha_dd->dma_lch_in.chan)); } spin_lock(&atmel_sha.lock); @@ -1419,7 +1469,9 @@ static int atmel_sha_probe(struct platform_device *pdev) if (err) goto err_algs; - dev_info(dev, "Atmel SHA1/SHA256\n"); + dev_info(dev, "Atmel SHA1/SHA256%s%s\n", + sha_dd->caps.has_sha224 ? "/SHA224" : "", + sha_dd->caps.has_sha_384_512 ? "/SHA384/SHA512" : ""); return 0; @@ -1483,6 +1535,7 @@ static struct platform_driver atmel_sha_driver = { .driver = { .name = "atmel_sha", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(atmel_sha_dt_ids), }, }; diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index 4a99564a08e6..6cde5b530c69 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -30,6 +30,7 @@ #include <linux/irq.h> #include <linux/scatterlist.h> #include <linux/dma-mapping.h> +#include <linux/of_device.h> #include <linux/delay.h> #include <linux/crypto.h> #include <linux/cryptohash.h> @@ -716,59 +717,50 @@ static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd, struct crypto_platform_data *pdata) { int err = -ENOMEM; - dma_cap_mask_t mask_in, mask_out; + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* Try to grab 2 DMA channels */ + dd->dma_lch_in.chan = dma_request_slave_channel_compat(mask, + atmel_tdes_filter, &pdata->dma_slave->rxdata, dd->dev, "tx"); + if (!dd->dma_lch_in.chan) + goto err_dma_in; + + dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; + dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + + TDES_IDATA1R; + dd->dma_lch_in.dma_conf.src_maxburst = 1; + dd->dma_lch_in.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.dst_maxburst = 1; + dd->dma_lch_in.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.device_fc = false; + + dd->dma_lch_out.chan = dma_request_slave_channel_compat(mask, + atmel_tdes_filter, &pdata->dma_slave->txdata, dd->dev, "rx"); + if (!dd->dma_lch_out.chan) + goto err_dma_out; + + dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; + dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + + TDES_ODATA1R; + dd->dma_lch_out.dma_conf.src_maxburst = 1; + dd->dma_lch_out.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_out.dma_conf.dst_maxburst = 1; + dd->dma_lch_out.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_out.dma_conf.device_fc = false; - if (pdata && pdata->dma_slave->txdata.dma_dev && - pdata->dma_slave->rxdata.dma_dev) { - - /* Try to grab 2 DMA channels */ - dma_cap_zero(mask_in); - dma_cap_set(DMA_SLAVE, mask_in); - - dd->dma_lch_in.chan = dma_request_channel(mask_in, - atmel_tdes_filter, &pdata->dma_slave->rxdata); - - if (!dd->dma_lch_in.chan) - goto err_dma_in; - - dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; - dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + - TDES_IDATA1R; - dd->dma_lch_in.dma_conf.src_maxburst = 1; - dd->dma_lch_in.dma_conf.src_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.dst_maxburst = 1; - dd->dma_lch_in.dma_conf.dst_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.device_fc = false; - - dma_cap_zero(mask_out); - dma_cap_set(DMA_SLAVE, mask_out); - dd->dma_lch_out.chan = dma_request_channel(mask_out, - atmel_tdes_filter, &pdata->dma_slave->txdata); - - if (!dd->dma_lch_out.chan) - goto err_dma_out; - - dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; - dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + - TDES_ODATA1R; - dd->dma_lch_out.dma_conf.src_maxburst = 1; - dd->dma_lch_out.dma_conf.src_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_out.dma_conf.dst_maxburst = 1; - dd->dma_lch_out.dma_conf.dst_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_out.dma_conf.device_fc = false; - - return 0; - } else { - return -ENODEV; - } + return 0; err_dma_out: dma_release_channel(dd->dma_lch_in.chan); err_dma_in: + dev_warn(dd->dev, "no DMA channel available\n"); return err; } @@ -1317,6 +1309,47 @@ static void atmel_tdes_get_cap(struct atmel_tdes_dev *dd) } } +#if defined(CONFIG_OF) +static const struct of_device_id atmel_tdes_dt_ids[] = { + { .compatible = "atmel,at91sam9g46-tdes" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, atmel_tdes_dt_ids); + +static struct crypto_platform_data *atmel_tdes_of_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct crypto_platform_data *pdata; + + if (!np) { + dev_err(&pdev->dev, "device node not found\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&pdev->dev, "could not allocate memory for pdata\n"); + return ERR_PTR(-ENOMEM); + } + + pdata->dma_slave = devm_kzalloc(&pdev->dev, + sizeof(*(pdata->dma_slave)), + GFP_KERNEL); + if (!pdata->dma_slave) { + dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); + devm_kfree(&pdev->dev, pdata); + return ERR_PTR(-ENOMEM); + } + + return pdata; +} +#else /* CONFIG_OF */ +static inline struct crypto_platform_data *atmel_tdes_of_init(struct platform_device *pdev) +{ + return ERR_PTR(-EINVAL); +} +#endif + static int atmel_tdes_probe(struct platform_device *pdev) { struct atmel_tdes_dev *tdes_dd; @@ -1399,13 +1432,24 @@ static int atmel_tdes_probe(struct platform_device *pdev) if (tdes_dd->caps.has_dma) { pdata = pdev->dev.platform_data; if (!pdata) { - dev_err(&pdev->dev, "platform data not available\n"); + pdata = atmel_tdes_of_init(pdev); + if (IS_ERR(pdata)) { + dev_err(&pdev->dev, "platform data not available\n"); + err = PTR_ERR(pdata); + goto err_pdata; + } + } + if (!pdata->dma_slave) { err = -ENXIO; goto err_pdata; } err = atmel_tdes_dma_init(tdes_dd, pdata); if (err) goto err_tdes_dma; + + dev_info(dev, "using %s, %s for DMA transfers\n", + dma_chan_name(tdes_dd->dma_lch_in.chan), + dma_chan_name(tdes_dd->dma_lch_out.chan)); } spin_lock(&atmel_tdes.lock); @@ -1487,6 +1531,7 @@ static struct platform_driver atmel_tdes_driver = { .driver = { .name = "atmel_tdes", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(atmel_tdes_dt_ids), }, }; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 50cc557abe41..697338772b64 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -115,6 +115,13 @@ config GPIO_CLPS711X help Say yes here to support GPIO on CLPS711X SoCs. +config GPIO_DAVINCI + bool "TI Davinci/Keystone GPIO support" + default y if ARCH_DAVINCI + depends on ARM && (ARCH_DAVINCI || ARCH_KEYSTONE) + help + Say yes here to enable GPIO support for TI Davinci/Keystone SoCs. + config GPIO_GENERIC_PLATFORM tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" select GPIO_GENERIC diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 0248471402e4..5d50179ece16 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o -obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o +obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o obj-$(CONFIG_GPIO_EM) += gpio-em.o obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 84be70157ad6..7629b4f12b7f 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -16,8 +16,13 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/platform_data/gpio-davinci.h> +#include <linux/irqchip/chained_irq.h> struct davinci_gpio_regs { u32 dir; @@ -82,14 +87,14 @@ static inline int __davinci_direction(struct gpio_chip *chip, u32 mask = 1 << offset; spin_lock_irqsave(&d->lock, flags); - temp = __raw_readl(&g->dir); + temp = readl_relaxed(&g->dir); if (out) { temp &= ~mask; - __raw_writel(mask, value ? &g->set_data : &g->clr_data); + writel_relaxed(mask, value ? &g->set_data : &g->clr_data); } else { temp |= mask; } - __raw_writel(temp, &g->dir); + writel_relaxed(temp, &g->dir); spin_unlock_irqrestore(&d->lock, flags); return 0; @@ -118,7 +123,7 @@ static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) struct davinci_gpio_controller *d = chip2controller(chip); struct davinci_gpio_regs __iomem *g = d->regs; - return (1 << offset) & __raw_readl(&g->in_data); + return (1 << offset) & readl_relaxed(&g->in_data); } /* @@ -130,7 +135,41 @@ davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) struct davinci_gpio_controller *d = chip2controller(chip); struct davinci_gpio_regs __iomem *g = d->regs; - __raw_writel((1 << offset), value ? &g->set_data : &g->clr_data); + writel_relaxed((1 << offset), value ? &g->set_data : &g->clr_data); +} + +static struct davinci_gpio_platform_data * +davinci_gpio_get_pdata(struct platform_device *pdev) +{ + struct device_node *dn = pdev->dev.of_node; + struct davinci_gpio_platform_data *pdata; + int ret; + u32 val; + + if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) + return pdev->dev.platform_data; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + ret = of_property_read_u32(dn, "ti,ngpio", &val); + if (ret) + goto of_err; + + pdata->ngpio = val; + + ret = of_property_read_u32(dn, "ti,davinci-gpio-unbanked", &val); + if (ret) + goto of_err; + + pdata->gpio_unbanked = val; + + return pdata; + +of_err: + dev_err(&pdev->dev, "Populating pdata from DT failed: err %d\n", ret); + return NULL; } static int davinci_gpio_probe(struct platform_device *pdev) @@ -143,12 +182,14 @@ static int davinci_gpio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct resource *res; - pdata = dev->platform_data; + pdata = davinci_gpio_get_pdata(pdev); if (!pdata) { dev_err(dev, "No platform data found\n"); return -EINVAL; } + dev->platform_data = pdata; + /* * The gpio banks conceptually expose a segmented bitmap, * and "ngpio" is one more than the largest zero-based @@ -160,8 +201,8 @@ static int davinci_gpio_probe(struct platform_device *pdev) return -EINVAL; } - if (WARN_ON(DAVINCI_N_GPIO < ngpio)) - ngpio = DAVINCI_N_GPIO; + if (WARN_ON(ARCH_NR_GPIOS < ngpio)) + ngpio = ARCH_NR_GPIOS; chips = devm_kzalloc(dev, ngpio * sizeof(struct davinci_gpio_controller), @@ -194,6 +235,9 @@ static int davinci_gpio_probe(struct platform_device *pdev) if (chips[i].chip.ngpio > 32) chips[i].chip.ngpio = 32; +#ifdef CONFIG_OF_GPIO + chips[i].chip.of_node = dev->of_node; +#endif spin_lock_init(&chips[i].lock); regs = gpio2regs(base); @@ -227,8 +271,8 @@ static void gpio_irq_disable(struct irq_data *d) struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); u32 mask = (u32) irq_data_get_irq_handler_data(d); - __raw_writel(mask, &g->clr_falling); - __raw_writel(mask, &g->clr_rising); + writel_relaxed(mask, &g->clr_falling); + writel_relaxed(mask, &g->clr_rising); } static void gpio_irq_enable(struct irq_data *d) @@ -242,9 +286,9 @@ static void gpio_irq_enable(struct irq_data *d) status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; if (status & IRQ_TYPE_EDGE_FALLING) - __raw_writel(mask, &g->set_falling); + writel_relaxed(mask, &g->set_falling); if (status & IRQ_TYPE_EDGE_RISING) - __raw_writel(mask, &g->set_rising); + writel_relaxed(mask, &g->set_rising); } static int gpio_irq_type(struct irq_data *d, unsigned trigger) @@ -278,34 +322,28 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc) mask <<= 16; /* temporarily mask (level sensitive) parent IRQ */ - desc->irq_data.chip->irq_mask(&desc->irq_data); - desc->irq_data.chip->irq_ack(&desc->irq_data); + chained_irq_enter(irq_desc_get_chip(desc), desc); while (1) { u32 status; - int n; - int res; + int bit; /* ack any irqs */ - status = __raw_readl(&g->intstat) & mask; + status = readl_relaxed(&g->intstat) & mask; if (!status) break; - __raw_writel(status, &g->intstat); + writel_relaxed(status, &g->intstat); /* now demux them to the right lowlevel handler */ - n = d->irq_base; - if (irq & 1) { - n += 16; - status >>= 16; - } while (status) { - res = ffs(status); - n += res; - generic_handle_irq(n - 1); - status >>= res; + bit = __ffs(status); + status &= ~BIT(bit); + generic_handle_irq( + irq_find_mapping(d->irq_domain, + d->chip.base + bit)); } } - desc->irq_data.chip->irq_unmask(&desc->irq_data); + chained_irq_exit(irq_desc_get_chip(desc), desc); /* now it may re-trigger */ } @@ -313,10 +351,10 @@ static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset) { struct davinci_gpio_controller *d = chip2controller(chip); - if (d->irq_base >= 0) - return d->irq_base + offset; + if (d->irq_domain) + return irq_create_mapping(d->irq_domain, d->chip.base + offset); else - return -ENODEV; + return -ENXIO; } static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) @@ -346,14 +384,35 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger) if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) return -EINVAL; - __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING) + writel_relaxed(mask, (trigger & IRQ_TYPE_EDGE_FALLING) ? &g->set_falling : &g->clr_falling); - __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING) + writel_relaxed(mask, (trigger & IRQ_TYPE_EDGE_RISING) ? &g->set_rising : &g->clr_rising); return 0; } +static int +davinci_gpio_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + struct davinci_gpio_regs __iomem *g = gpio2regs(hw); + + irq_set_chip_and_handler_name(irq, &gpio_irqchip, handle_simple_irq, + "davinci_gpio"); + irq_set_irq_type(irq, IRQ_TYPE_NONE); + irq_set_chip_data(irq, (__force void *)g); + irq_set_handler_data(irq, (void *)__gpio_mask(hw)); + set_irq_flags(irq, IRQF_VALID); + + return 0; +} + +static const struct irq_domain_ops davinci_gpio_irq_ops = { + .map = davinci_gpio_irq_map, + .xlate = irq_domain_xlate_onetwocell, +}; + /* * NOTE: for suspend/resume, probably best to make a platform_device with * suspend_late/resume_resume calls hooking into results of the set_wake() @@ -373,6 +432,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) struct davinci_gpio_controller *chips = platform_get_drvdata(pdev); struct davinci_gpio_platform_data *pdata = dev->platform_data; struct davinci_gpio_regs __iomem *g; + struct irq_domain *irq_domain = NULL; ngpio = pdata->ngpio; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); @@ -396,6 +456,22 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) } clk_prepare_enable(clk); + if (!pdata->gpio_unbanked) { + irq = irq_alloc_descs(-1, 0, ngpio, 0); + if (irq < 0) { + dev_err(dev, "Couldn't allocate IRQ numbers\n"); + return irq; + } + + irq_domain = irq_domain_add_legacy(NULL, ngpio, irq, 0, + &davinci_gpio_irq_ops, + chips); + if (!irq_domain) { + dev_err(dev, "Couldn't register an IRQ domain\n"); + return -ENODEV; + } + } + /* * Arrange gpio_to_irq() support, handling either direct IRQs or * banked IRQs. Having GPIOs in the first GPIO bank use direct @@ -404,9 +480,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) */ for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) { chips[bank].chip.to_irq = gpio_to_irq_banked; - chips[bank].irq_base = pdata->gpio_unbanked - ? -EINVAL - : (pdata->intc_irq_num + gpio); + chips[bank].irq_domain = irq_domain; } /* @@ -432,8 +506,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) /* default trigger: both edges */ g = gpio2regs(0); - __raw_writel(~0, &g->set_falling); - __raw_writel(~0, &g->set_rising); + writel_relaxed(~0, &g->set_falling); + writel_relaxed(~0, &g->set_rising); /* set the direct IRQs up to use that irqchip */ for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) { @@ -449,15 +523,11 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we * then chain through our own handler. */ - for (gpio = 0, irq = gpio_to_irq(0), bank = 0; - gpio < ngpio; - bank++, bank_irq++) { - unsigned i; - + for (gpio = 0, bank = 0; gpio < ngpio; bank++, bank_irq++, gpio += 16) { /* disabled by default, enabled only as needed */ g = gpio2regs(gpio); - __raw_writel(~0, &g->clr_falling); - __raw_writel(~0, &g->clr_rising); + writel_relaxed(~0, &g->clr_falling); + writel_relaxed(~0, &g->clr_rising); /* set up all irqs in this bank */ irq_set_chained_handler(bank_irq, gpio_irq_handler); @@ -469,14 +539,6 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) */ irq_set_handler_data(bank_irq, &chips[gpio / 32]); - for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { - irq_set_chip(irq, &gpio_irqchip); - irq_set_chip_data(irq, (__force void *)g); - irq_set_handler_data(irq, (void *)__gpio_mask(gpio)); - irq_set_handler(irq, handle_simple_irq); - set_irq_flags(irq, IRQF_VALID); - } - binten |= BIT(bank); } @@ -485,18 +547,25 @@ done: * BINTEN -- per-bank interrupt enable. genirq would also let these * bits be set/cleared dynamically. */ - __raw_writel(binten, gpio_base + BINTEN); - - printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0)); + writel_relaxed(binten, gpio_base + BINTEN); return 0; } +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id davinci_gpio_ids[] = { + { .compatible = "ti,dm6441-gpio", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, davinci_gpio_ids); +#endif + static struct platform_driver davinci_gpio_driver = { .probe = davinci_gpio_probe, .driver = { - .name = "davinci_gpio", - .owner = THIS_MODULE, + .name = "davinci_gpio", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(davinci_gpio_ids), }, }; diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c index 868ed40cb6bf..40e6440348ff 100644 --- a/drivers/irqchip/exynos-combiner.c +++ b/drivers/irqchip/exynos-combiner.c @@ -171,8 +171,7 @@ static struct irq_domain_ops combiner_irq_domain_ops = { static void __init combiner_init(void __iomem *combiner_base, struct device_node *np, - unsigned int max_nr, - int irq_base) + unsigned int max_nr) { int i, irq; unsigned int nr_irq; @@ -186,7 +185,7 @@ static void __init combiner_init(void __iomem *combiner_base, return; } - combiner_irq_domain = irq_domain_add_simple(np, nr_irq, irq_base, + combiner_irq_domain = irq_domain_add_linear(np, nr_irq, &combiner_irq_domain_ops, combiner_data); if (WARN_ON(!combiner_irq_domain)) { pr_warning("%s: irq domain init failed\n", __func__); @@ -207,7 +206,6 @@ static int __init combiner_of_init(struct device_node *np, { void __iomem *combiner_base; unsigned int max_nr = 20; - int irq_base = -1; combiner_base = of_iomap(np, 0); if (!combiner_base) { @@ -221,14 +219,7 @@ static int __init combiner_of_init(struct device_node *np, __func__, max_nr); } - /* - * FIXME: This is a hardwired COMBINER_IRQ(0,0). Once all devices - * get their IRQ from DT, remove this in order to get dynamic - * allocation. - */ - irq_base = 160; - - combiner_init(combiner_base, np, max_nr, irq_base); + combiner_init(combiner_base, np, max_nr); return 0; } diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c index 2f404ba61c6c..8777065012a5 100644 --- a/drivers/irqchip/irq-renesas-irqc.c +++ b/drivers/irqchip/irq-renesas-irqc.c @@ -81,15 +81,12 @@ static void irqc_irq_disable(struct irq_data *d) iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_STS); } -#define INTC_IRQ_SENSE_VALID 0x10 -#define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID) - static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = { - [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x01), - [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x02), - [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x04), /* Synchronous */ - [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x08), /* Synchronous */ - [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x0c), /* Synchronous */ + [IRQ_TYPE_LEVEL_LOW] = 0x01, + [IRQ_TYPE_LEVEL_HIGH] = 0x02, + [IRQ_TYPE_EDGE_FALLING] = 0x04, /* Synchronous */ + [IRQ_TYPE_EDGE_RISING] = 0x08, /* Synchronous */ + [IRQ_TYPE_EDGE_BOTH] = 0x0c, /* Synchronous */ }; static int irqc_irq_set_type(struct irq_data *d, unsigned int type) @@ -101,12 +98,12 @@ static int irqc_irq_set_type(struct irq_data *d, unsigned int type) irqc_dbg(&p->irq[hw_irq], "sense"); - if (!(value & INTC_IRQ_SENSE_VALID)) + if (!value) return -EINVAL; tmp = ioread32(p->iomem + IRQC_CONFIG(hw_irq)); tmp &= ~0x3f; - tmp |= value ^ INTC_IRQ_SENSE_VALID; + tmp |= value; iowrite32(tmp, p->iomem + IRQC_CONFIG(hw_irq)); return 0; } @@ -212,10 +209,8 @@ static int irqc_probe(struct platform_device *pdev) irq_chip->name = name; irq_chip->irq_mask = irqc_irq_disable; irq_chip->irq_unmask = irqc_irq_enable; - irq_chip->irq_enable = irqc_irq_enable; - irq_chip->irq_disable = irqc_irq_disable; irq_chip->irq_set_type = irqc_irq_set_type; - irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; + irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, p->number_of_irqs, diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c index 47a52ab580d8..3ae2bb8d9cf2 100644 --- a/drivers/irqchip/irq-versatile-fpga.c +++ b/drivers/irqchip/irq-versatile-fpga.c @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/of_irq.h> #include <asm/exception.h> #include <asm/mach/irq.h> @@ -167,8 +168,12 @@ void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start, f->used_irqs++; } - pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n", + pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs", fpga_irq_id, name, base, f->used_irqs); + if (parent_irq != -1) + pr_cont(", parent IRQ: %d\n", parent_irq); + else + pr_cont("\n"); fpga_irq_id++; } @@ -180,6 +185,7 @@ int __init fpga_irq_of_init(struct device_node *node, void __iomem *base; u32 clear_mask; u32 valid_mask; + int parent_irq; if (WARN_ON(!node)) return -ENODEV; @@ -193,7 +199,12 @@ int __init fpga_irq_of_init(struct device_node *node, if (of_property_read_u32(node, "valid-mask", &valid_mask)) valid_mask = 0; - fpga_irq_init(base, node->name, 0, -1, valid_mask, node); + /* Some chips are cascaded from a parent IRQ */ + parent_irq = irq_of_parse_and_map(node, 0); + if (!parent_irq) + parent_irq = -1; + + fpga_irq_init(base, node->name, 0, parent_irq, valid_mask, node); writel(clear_mask, base + IRQ_ENABLE_CLEAR); writel(clear_mask, base + FIQ_ENABLE_CLEAR); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 7fc5099e44b2..4e8ca9d5570f 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -324,7 +324,7 @@ config MMC_ATMELMCI config MMC_MSM tristate "Qualcomm SDCC Controller Support" - depends on MMC && ARCH_MSM + depends on MMC && (ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50) help This provides support for the SD/MMC cell found in the MSM and QSD SOCs from Qualcomm. The controller also has diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 007730222116..b1328a45b095 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -304,6 +304,17 @@ config RTC_DRV_ISL12022 This driver can also be built as a module. If so, the module will be called rtc-isl12022. +config RTC_DRV_ISL12057 + depends on I2C + select REGMAP_I2C + tristate "Intersil ISL12057" + help + If you say yes here you get support for the Intersil ISL12057 + I2C RTC chip. + + This driver can also be built as a module. If so, the module + will be called rtc-isl12057. + config RTC_DRV_X1205 tristate "Xicor/Intersil X1205" help @@ -1104,6 +1115,13 @@ config RTC_DRV_SUN4V If you say Y here you will get support for the Hypervisor based RTC on SUN4V systems. +config RTC_DRV_SUNXI + tristate "Allwinner sun4i/sun7i RTC" + depends on ARCH_SUNXI + help + If you say Y here you will get support for the RTC found on + Allwinner A10/A20. + config RTC_DRV_STARFIRE bool "Starfire RTC" depends on SPARC64 diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 27b4bd884066..c00741a0bf10 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o +obj-$(CONFIG_RTC_DRV_ISL12057) += rtc-isl12057.o obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o @@ -117,6 +118,7 @@ obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o +obj-$(CONFIG_RTC_DRV_SUNXI) += rtc-sunxi.o obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c new file mode 100644 index 000000000000..7854a656628f --- /dev/null +++ b/drivers/rtc/rtc-isl12057.c @@ -0,0 +1,310 @@ +/* + * rtc-isl12057 - Driver for Intersil ISL12057 I2C Real Time Clock + * + * Copyright (C) 2013, Arnaud EBALARD <arno@natisbad.org> + * + * This work is largely based on Intersil ISL1208 driver developed by + * Hebert Valerio Riedel <hvr@gnu.org>. + * + * Detailed datasheet on which this development is based is available here: + * + * http://natisbad.org/NAS2/refs/ISL12057.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/rtc.h> +#include <linux/i2c.h> +#include <linux/bcd.h> +#include <linux/rtc.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/regmap.h> + +#define DRV_NAME "rtc-isl12057" + +/* RTC section */ +#define ISL12057_REG_RTC_SC 0x00 /* Seconds */ +#define ISL12057_REG_RTC_MN 0x01 /* Minutes */ +#define ISL12057_REG_RTC_HR 0x02 /* Hours */ +#define ISL12057_REG_RTC_HR_PM BIT(5) /* AM/PM bit in 12h format */ +#define ISL12057_REG_RTC_HR_MIL BIT(6) /* 24h/12h format */ +#define ISL12057_REG_RTC_DW 0x03 /* Day of the Week */ +#define ISL12057_REG_RTC_DT 0x04 /* Date */ +#define ISL12057_REG_RTC_MO 0x05 /* Month */ +#define ISL12057_REG_RTC_YR 0x06 /* Year */ +#define ISL12057_RTC_SEC_LEN 7 + +/* Alarm 1 section */ +#define ISL12057_REG_A1_SC 0x07 /* Alarm 1 Seconds */ +#define ISL12057_REG_A1_MN 0x08 /* Alarm 1 Minutes */ +#define ISL12057_REG_A1_HR 0x09 /* Alarm 1 Hours */ +#define ISL12057_REG_A1_HR_PM BIT(5) /* AM/PM bit in 12h format */ +#define ISL12057_REG_A1_HR_MIL BIT(6) /* 24h/12h format */ +#define ISL12057_REG_A1_DWDT 0x0A /* Alarm 1 Date / Day of the week */ +#define ISL12057_REG_A1_DWDT_B BIT(6) /* DW / DT selection bit */ +#define ISL12057_A1_SEC_LEN 4 + +/* Alarm 2 section */ +#define ISL12057_REG_A2_MN 0x0B /* Alarm 2 Minutes */ +#define ISL12057_REG_A2_HR 0x0C /* Alarm 2 Hours */ +#define ISL12057_REG_A2_DWDT 0x0D /* Alarm 2 Date / Day of the week */ +#define ISL12057_A2_SEC_LEN 3 + +/* Control/Status registers */ +#define ISL12057_REG_INT 0x0E +#define ISL12057_REG_INT_A1IE BIT(0) /* Alarm 1 interrupt enable bit */ +#define ISL12057_REG_INT_A2IE BIT(1) /* Alarm 2 interrupt enable bit */ +#define ISL12057_REG_INT_INTCN BIT(2) /* Interrupt control enable bit */ +#define ISL12057_REG_INT_RS1 BIT(3) /* Freq out control bit 1 */ +#define ISL12057_REG_INT_RS2 BIT(4) /* Freq out control bit 2 */ +#define ISL12057_REG_INT_EOSC BIT(7) /* Oscillator enable bit */ + +#define ISL12057_REG_SR 0x0F +#define ISL12057_REG_SR_A1F BIT(0) /* Alarm 1 interrupt bit */ +#define ISL12057_REG_SR_A2F BIT(1) /* Alarm 2 interrupt bit */ +#define ISL12057_REG_SR_OSF BIT(7) /* Oscillator failure bit */ + +/* Register memory map length */ +#define ISL12057_MEM_MAP_LEN 0x10 + +struct isl12057_rtc_data { + struct regmap *regmap; + struct mutex lock; +}; + +static void isl12057_rtc_regs_to_tm(struct rtc_time *tm, u8 *regs) +{ + tm->tm_sec = bcd2bin(regs[ISL12057_REG_RTC_SC]); + tm->tm_min = bcd2bin(regs[ISL12057_REG_RTC_MN]); + + if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_MIL) { /* AM/PM */ + tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x0f); + if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_PM) + tm->tm_hour += 12; + } else { /* 24 hour mode */ + tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x3f); + } + + tm->tm_mday = bcd2bin(regs[ISL12057_REG_RTC_DT]); + tm->tm_wday = bcd2bin(regs[ISL12057_REG_RTC_DW]) - 1; /* starts at 1 */ + tm->tm_mon = bcd2bin(regs[ISL12057_REG_RTC_MO]) - 1; /* starts at 1 */ + tm->tm_year = bcd2bin(regs[ISL12057_REG_RTC_YR]) + 100; +} + +static int isl12057_rtc_tm_to_regs(u8 *regs, struct rtc_time *tm) +{ + /* + * The clock has an 8 bit wide bcd-coded register for the year. + * tm_year is an offset from 1900 and we are interested in the + * 2000-2099 range, so any value less than 100 is invalid. + */ + if (tm->tm_year < 100) + return -EINVAL; + + regs[ISL12057_REG_RTC_SC] = bin2bcd(tm->tm_sec); + regs[ISL12057_REG_RTC_MN] = bin2bcd(tm->tm_min); + regs[ISL12057_REG_RTC_HR] = bin2bcd(tm->tm_hour); /* 24-hour format */ + regs[ISL12057_REG_RTC_DT] = bin2bcd(tm->tm_mday); + regs[ISL12057_REG_RTC_MO] = bin2bcd(tm->tm_mon + 1); + regs[ISL12057_REG_RTC_YR] = bin2bcd(tm->tm_year - 100); + regs[ISL12057_REG_RTC_DW] = bin2bcd(tm->tm_wday + 1); + + return 0; +} + +/* + * Try and match register bits w/ fixed null values to see whether we + * are dealing with an ISL12057. Note: this function is called early + * during init and hence does need mutex protection. + */ +static int isl12057_i2c_validate_chip(struct regmap *regmap) +{ + u8 regs[ISL12057_MEM_MAP_LEN]; + static const u8 mask[ISL12057_MEM_MAP_LEN] = { 0x80, 0x80, 0x80, 0xf8, + 0xc0, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x7c }; + int ret, i; + + ret = regmap_bulk_read(regmap, 0, regs, ISL12057_MEM_MAP_LEN); + if (ret) + return ret; + + for (i = 0; i < ISL12057_MEM_MAP_LEN; ++i) { + if (regs[i] & mask[i]) /* check if bits are cleared */ + return -ENODEV; + } + + return 0; +} + +static int isl12057_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct isl12057_rtc_data *data = dev_get_drvdata(dev); + u8 regs[ISL12057_RTC_SEC_LEN]; + int ret; + + mutex_lock(&data->lock); + ret = regmap_bulk_read(data->regmap, ISL12057_REG_RTC_SC, regs, + ISL12057_RTC_SEC_LEN); + mutex_unlock(&data->lock); + + if (ret) { + dev_err(dev, "%s: RTC read failed\n", __func__); + return ret; + } + + isl12057_rtc_regs_to_tm(tm, regs); + + return rtc_valid_tm(tm); +} + +static int isl12057_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct isl12057_rtc_data *data = dev_get_drvdata(dev); + u8 regs[ISL12057_RTC_SEC_LEN]; + int ret; + + ret = isl12057_rtc_tm_to_regs(regs, tm); + if (ret) + return ret; + + mutex_lock(&data->lock); + ret = regmap_bulk_write(data->regmap, ISL12057_REG_RTC_SC, regs, + ISL12057_RTC_SEC_LEN); + mutex_unlock(&data->lock); + + if (ret) + dev_err(dev, "%s: RTC write failed\n", __func__); + + return ret; +} + +/* + * Check current RTC status and enable/disable what needs to be. Return 0 if + * everything went ok and a negative value upon error. Note: this function + * is called early during init and hence does need mutex protection. + */ +static int isl12057_check_rtc_status(struct device *dev, struct regmap *regmap) +{ + int ret; + + /* Enable oscillator if not already running */ + ret = regmap_update_bits(regmap, ISL12057_REG_INT, + ISL12057_REG_INT_EOSC, 0); + if (ret < 0) { + dev_err(dev, "Unable to enable oscillator\n"); + return ret; + } + + /* Clear oscillator failure bit if needed */ + ret = regmap_update_bits(regmap, ISL12057_REG_SR, + ISL12057_REG_SR_OSF, 0); + if (ret < 0) { + dev_err(dev, "Unable to clear oscillator failure bit\n"); + return ret; + } + + /* Clear alarm bit if needed */ + ret = regmap_update_bits(regmap, ISL12057_REG_SR, + ISL12057_REG_SR_A1F, 0); + if (ret < 0) { + dev_err(dev, "Unable to clear alarm bit\n"); + return ret; + } + + return 0; +} + +static const struct rtc_class_ops rtc_ops = { + .read_time = isl12057_rtc_read_time, + .set_time = isl12057_rtc_set_time, +}; + +static struct regmap_config isl12057_rtc_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int isl12057_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct isl12057_rtc_data *data; + struct rtc_device *rtc; + struct regmap *regmap; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) + return -ENODEV; + + regmap = devm_regmap_init_i2c(client, &isl12057_rtc_regmap_config); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(dev, "regmap allocation failed: %d\n", ret); + return ret; + } + + ret = isl12057_i2c_validate_chip(regmap); + if (ret) + return ret; + + ret = isl12057_check_rtc_status(dev, regmap); + if (ret) + return ret; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + mutex_init(&data->lock); + data->regmap = regmap; + dev_set_drvdata(dev, data); + + rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + return 0; +} + +#ifdef CONFIG_OF +static struct of_device_id isl12057_dt_match[] = { + { .compatible = "isl,isl12057" }, + { }, +}; +#endif + +static const struct i2c_device_id isl12057_id[] = { + { "isl12057", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, isl12057_id); + +static struct i2c_driver isl12057_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(isl12057_dt_match), + }, + .probe = isl12057_probe, + .id_table = isl12057_id, +}; +module_i2c_driver(isl12057_driver); + +MODULE_AUTHOR("Arnaud EBALARD <arno@natisbad.org>"); +MODULE_DESCRIPTION("Intersil ISL12057 RTC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c new file mode 100644 index 000000000000..68a35284e5ad --- /dev/null +++ b/drivers/rtc/rtc-sunxi.c @@ -0,0 +1,523 @@ +/* + * An RTC driver for Allwinner A10/A20 + * + * Copyright (c) 2013, Carlo Caione <carlo.caione@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> +#include <linux/types.h> + +#define SUNXI_LOSC_CTRL 0x0000 +#define SUNXI_LOSC_CTRL_RTC_HMS_ACC BIT(8) +#define SUNXI_LOSC_CTRL_RTC_YMD_ACC BIT(7) + +#define SUNXI_RTC_YMD 0x0004 + +#define SUNXI_RTC_HMS 0x0008 + +#define SUNXI_ALRM_DHMS 0x000c + +#define SUNXI_ALRM_EN 0x0014 +#define SUNXI_ALRM_EN_CNT_EN BIT(8) + +#define SUNXI_ALRM_IRQ_EN 0x0018 +#define SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN BIT(0) + +#define SUNXI_ALRM_IRQ_STA 0x001c +#define SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND BIT(0) + +#define SUNXI_MASK_DH 0x0000001f +#define SUNXI_MASK_SM 0x0000003f +#define SUNXI_MASK_M 0x0000000f +#define SUNXI_MASK_LY 0x00000001 +#define SUNXI_MASK_D 0x00000ffe +#define SUNXI_MASK_M 0x0000000f + +#define SUNXI_GET(x, mask, shift) (((x) & ((mask) << (shift))) \ + >> (shift)) + +#define SUNXI_SET(x, mask, shift) (((x) & (mask)) << (shift)) + +/* + * Get date values + */ +#define SUNXI_DATE_GET_DAY_VALUE(x) SUNXI_GET(x, SUNXI_MASK_DH, 0) +#define SUNXI_DATE_GET_MON_VALUE(x) SUNXI_GET(x, SUNXI_MASK_M, 8) +#define SUNXI_DATE_GET_YEAR_VALUE(x, mask) SUNXI_GET(x, mask, 16) + +/* + * Get time values + */ +#define SUNXI_TIME_GET_SEC_VALUE(x) SUNXI_GET(x, SUNXI_MASK_SM, 0) +#define SUNXI_TIME_GET_MIN_VALUE(x) SUNXI_GET(x, SUNXI_MASK_SM, 8) +#define SUNXI_TIME_GET_HOUR_VALUE(x) SUNXI_GET(x, SUNXI_MASK_DH, 16) + +/* + * Get alarm values + */ +#define SUNXI_ALRM_GET_SEC_VALUE(x) SUNXI_GET(x, SUNXI_MASK_SM, 0) +#define SUNXI_ALRM_GET_MIN_VALUE(x) SUNXI_GET(x, SUNXI_MASK_SM, 8) +#define SUNXI_ALRM_GET_HOUR_VALUE(x) SUNXI_GET(x, SUNXI_MASK_DH, 16) + +/* + * Set date values + */ +#define SUNXI_DATE_SET_DAY_VALUE(x) SUNXI_DATE_GET_DAY_VALUE(x) +#define SUNXI_DATE_SET_MON_VALUE(x) SUNXI_SET(x, SUNXI_MASK_M, 8) +#define SUNXI_DATE_SET_YEAR_VALUE(x, mask) SUNXI_SET(x, mask, 16) +#define SUNXI_LEAP_SET_VALUE(x, shift) SUNXI_SET(x, SUNXI_MASK_LY, shift) + +/* + * Set time values + */ +#define SUNXI_TIME_SET_SEC_VALUE(x) SUNXI_TIME_GET_SEC_VALUE(x) +#define SUNXI_TIME_SET_MIN_VALUE(x) SUNXI_SET(x, SUNXI_MASK_SM, 8) +#define SUNXI_TIME_SET_HOUR_VALUE(x) SUNXI_SET(x, SUNXI_MASK_DH, 16) + +/* + * Set alarm values + */ +#define SUNXI_ALRM_SET_SEC_VALUE(x) SUNXI_ALRM_GET_SEC_VALUE(x) +#define SUNXI_ALRM_SET_MIN_VALUE(x) SUNXI_SET(x, SUNXI_MASK_SM, 8) +#define SUNXI_ALRM_SET_HOUR_VALUE(x) SUNXI_SET(x, SUNXI_MASK_DH, 16) +#define SUNXI_ALRM_SET_DAY_VALUE(x) SUNXI_SET(x, SUNXI_MASK_D, 21) + +/* + * Time unit conversions + */ +#define SEC_IN_MIN 60 +#define SEC_IN_HOUR (60 * SEC_IN_MIN) +#define SEC_IN_DAY (24 * SEC_IN_HOUR) + +/* + * The year parameter passed to the driver is usually an offset relative to + * the year 1900. This macro is used to convert this offset to another one + * relative to the minimum year allowed by the hardware. + */ +#define SUNXI_YEAR_OFF(x) ((x)->min - 1900) + +/* + * min and max year are arbitrary set considering the limited range of the + * hardware register field + */ +struct sunxi_rtc_data_year { + unsigned int min; /* min year allowed */ + unsigned int max; /* max year allowed */ + unsigned int mask; /* mask for the year field */ + unsigned char leap_shift; /* bit shift to get the leap year */ +}; + +static struct sunxi_rtc_data_year data_year_param[] = { + [0] = { + .min = 2010, + .max = 2073, + .mask = 0x3f, + .leap_shift = 22, + }, + [1] = { + .min = 1970, + .max = 2225, + .mask = 0xff, + .leap_shift = 24, + }, +}; + +struct sunxi_rtc_dev { + struct rtc_device *rtc; + struct device *dev; + struct sunxi_rtc_data_year *data_year; + void __iomem *base; + int irq; +}; + +static irqreturn_t sunxi_rtc_alarmirq(int irq, void *id) +{ + struct sunxi_rtc_dev *chip = (struct sunxi_rtc_dev *) id; + u32 val; + + val = readl(chip->base + SUNXI_ALRM_IRQ_STA); + + if (val & SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND) { + val |= SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND; + writel(val, chip->base + SUNXI_ALRM_IRQ_STA); + + rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void sunxi_rtc_setaie(int to, struct sunxi_rtc_dev *chip) +{ + u32 alrm_val = 0; + u32 alrm_irq_val = 0; + + if (to) { + alrm_val = readl(chip->base + SUNXI_ALRM_EN); + alrm_val |= SUNXI_ALRM_EN_CNT_EN; + + alrm_irq_val = readl(chip->base + SUNXI_ALRM_IRQ_EN); + alrm_irq_val |= SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN; + } else { + writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND, + chip->base + SUNXI_ALRM_IRQ_STA); + } + + writel(alrm_val, chip->base + SUNXI_ALRM_EN); + writel(alrm_irq_val, chip->base + SUNXI_ALRM_IRQ_EN); +} + +static int sunxi_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); + struct rtc_time *alrm_tm = &wkalrm->time; + u32 alrm; + u32 alrm_en; + u32 date; + + alrm = readl(chip->base + SUNXI_ALRM_DHMS); + date = readl(chip->base + SUNXI_RTC_YMD); + + alrm_tm->tm_sec = SUNXI_ALRM_GET_SEC_VALUE(alrm); + alrm_tm->tm_min = SUNXI_ALRM_GET_MIN_VALUE(alrm); + alrm_tm->tm_hour = SUNXI_ALRM_GET_HOUR_VALUE(alrm); + + alrm_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date); + alrm_tm->tm_mon = SUNXI_DATE_GET_MON_VALUE(date); + alrm_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date, + chip->data_year->mask); + + alrm_tm->tm_mon -= 1; + + /* + * switch from (data_year->min)-relative offset to + * a (1900)-relative one + */ + alrm_tm->tm_year += SUNXI_YEAR_OFF(chip->data_year); + + alrm_en = readl(chip->base + SUNXI_ALRM_IRQ_EN); + if (alrm_en & SUNXI_ALRM_EN_CNT_EN) + wkalrm->enabled = 1; + + return 0; +} + +static int sunxi_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) +{ + struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); + u32 date, time; + + /* + * read again in case it changes + */ + do { + date = readl(chip->base + SUNXI_RTC_YMD); + time = readl(chip->base + SUNXI_RTC_HMS); + } while ((date != readl(chip->base + SUNXI_RTC_YMD)) || + (time != readl(chip->base + SUNXI_RTC_HMS))); + + rtc_tm->tm_sec = SUNXI_TIME_GET_SEC_VALUE(time); + rtc_tm->tm_min = SUNXI_TIME_GET_MIN_VALUE(time); + rtc_tm->tm_hour = SUNXI_TIME_GET_HOUR_VALUE(time); + + rtc_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date); + rtc_tm->tm_mon = SUNXI_DATE_GET_MON_VALUE(date); + rtc_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date, + chip->data_year->mask); + + rtc_tm->tm_mon -= 1; + + /* + * switch from (data_year->min)-relative offset to + * a (1900)-relative one + */ + rtc_tm->tm_year += SUNXI_YEAR_OFF(chip->data_year); + + return rtc_valid_tm(rtc_tm); +} + +static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); + struct rtc_time *alrm_tm = &wkalrm->time; + struct rtc_time tm_now; + u32 alrm = 0; + unsigned long time_now = 0; + unsigned long time_set = 0; + unsigned long time_gap = 0; + unsigned long time_gap_day = 0; + unsigned long time_gap_hour = 0; + unsigned long time_gap_min = 0; + int ret = 0; + + ret = sunxi_rtc_gettime(dev, &tm_now); + if (ret < 0) { + dev_err(dev, "Error in getting time\n"); + return -EINVAL; + } + + rtc_tm_to_time(alrm_tm, &time_set); + rtc_tm_to_time(&tm_now, &time_now); + if (time_set <= time_now) { + dev_err(dev, "Date to set in the past\n"); + return -EINVAL; + } + + time_gap = time_set - time_now; + time_gap_day = time_gap / SEC_IN_DAY; + time_gap -= time_gap_day * SEC_IN_DAY; + time_gap_hour = time_gap / SEC_IN_HOUR; + time_gap -= time_gap_hour * SEC_IN_HOUR; + time_gap_min = time_gap / SEC_IN_MIN; + time_gap -= time_gap_min * SEC_IN_MIN; + + if (time_gap_day > 255) { + dev_err(dev, "Day must be in the range 0 - 255\n"); + return -EINVAL; + } + + sunxi_rtc_setaie(0, chip); + writel(0, chip->base + SUNXI_ALRM_DHMS); + usleep_range(100, 300); + + alrm = SUNXI_ALRM_SET_SEC_VALUE(time_gap) | + SUNXI_ALRM_SET_MIN_VALUE(time_gap_min) | + SUNXI_ALRM_SET_HOUR_VALUE(time_gap_hour) | + SUNXI_ALRM_SET_DAY_VALUE(time_gap_day); + writel(alrm, chip->base + SUNXI_ALRM_DHMS); + + writel(0, chip->base + SUNXI_ALRM_IRQ_EN); + writel(SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN, chip->base + SUNXI_ALRM_IRQ_EN); + + sunxi_rtc_setaie(wkalrm->enabled, chip); + + return 0; +} + +static int sunxi_rtc_wait(struct sunxi_rtc_dev *chip, int offset, + unsigned int mask, unsigned int ms_timeout) +{ + const unsigned long timeout = jiffies + msecs_to_jiffies(ms_timeout); + u32 reg; + + do { + reg = readl(chip->base + offset); + reg &= mask; + + if (reg == mask) + return 0; + + } while (time_before(jiffies, timeout)); + + return -ETIMEDOUT; +} + +static int sunxi_rtc_settime(struct device *dev, struct rtc_time *rtc_tm) +{ + struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); + u32 date = 0; + u32 time = 0; + int year; + + /* + * the input rtc_tm->tm_year is the offset relative to 1900. We use + * the SUNXI_YEAR_OFF macro to rebase it with respect to the min year + * allowed by the hardware + */ + + year = rtc_tm->tm_year + 1900; + if (year < chip->data_year->min || year > chip->data_year->max) { + dev_err(dev, "rtc only supports year in range %d - %d\n", + chip->data_year->min, chip->data_year->max); + return -EINVAL; + } + + rtc_tm->tm_year -= SUNXI_YEAR_OFF(chip->data_year); + rtc_tm->tm_mon += 1; + + date = SUNXI_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | + SUNXI_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | + SUNXI_DATE_SET_YEAR_VALUE(rtc_tm->tm_year, + chip->data_year->mask); + + if (is_leap_year(year)) + date |= SUNXI_LEAP_SET_VALUE(1, chip->data_year->leap_shift); + + time = SUNXI_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | + SUNXI_TIME_SET_MIN_VALUE(rtc_tm->tm_min) | + SUNXI_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour); + + writel(0, chip->base + SUNXI_RTC_HMS); + writel(0, chip->base + SUNXI_RTC_YMD); + + writel(time, chip->base + SUNXI_RTC_HMS); + + /* + * After writing the RTC HH-MM-SS register, the + * SUNXI_LOSC_CTRL_RTC_HMS_ACC bit is set and it will not + * be cleared until the real writing operation is finished + */ + + if (sunxi_rtc_wait(chip, SUNXI_LOSC_CTRL, + SUNXI_LOSC_CTRL_RTC_HMS_ACC, 50)) { + dev_err(dev, "Failed to set rtc time.\n"); + return -1; + } + + writel(date, chip->base + SUNXI_RTC_YMD); + + /* + * After writing the RTC YY-MM-DD register, the + * SUNXI_LOSC_CTRL_RTC_YMD_ACC bit is set and it will not + * be cleared until the real writing operation is finished + */ + + if (sunxi_rtc_wait(chip, SUNXI_LOSC_CTRL, + SUNXI_LOSC_CTRL_RTC_YMD_ACC, 50)) { + dev_err(dev, "Failed to set rtc time.\n"); + return -1; + } + + return 0; +} + +static int sunxi_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); + + if (!enabled) + sunxi_rtc_setaie(enabled, chip); + + return 0; +} + +static const struct rtc_class_ops sunxi_rtc_ops = { + .read_time = sunxi_rtc_gettime, + .set_time = sunxi_rtc_settime, + .read_alarm = sunxi_rtc_getalarm, + .set_alarm = sunxi_rtc_setalarm, + .alarm_irq_enable = sunxi_rtc_alarm_irq_enable +}; + +static const struct of_device_id sunxi_rtc_dt_ids[] = { + { .compatible = "allwinner,sun4i-rtc", .data = &data_year_param[0] }, + { .compatible = "allwinner,sun7i-a20-rtc", .data = &data_year_param[1] }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, sunxi_rtc_dt_ids); + +static int sunxi_rtc_probe(struct platform_device *pdev) +{ + struct sunxi_rtc_dev *chip; + struct resource *res; + const struct of_device_id *of_id; + int ret; + + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + platform_set_drvdata(pdev, chip); + chip->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + chip->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(chip->base)) + return PTR_ERR(chip->base); + + chip->irq = platform_get_irq(pdev, 0); + if (chip->irq < 0) { + dev_err(&pdev->dev, "No IRQ resource\n"); + return chip->irq; + } + ret = devm_request_irq(&pdev->dev, chip->irq, sunxi_rtc_alarmirq, + 0, dev_name(&pdev->dev), chip); + if (ret) { + dev_err(&pdev->dev, "Could not request IRQ\n"); + return ret; + } + + of_id = of_match_device(sunxi_rtc_dt_ids, &pdev->dev); + if (!of_id) { + dev_err(&pdev->dev, "Unable to setup RTC data\n"); + return -ENODEV; + } + chip->data_year = (struct sunxi_rtc_data_year *) of_id->data; + + /* clear the alarm count value */ + writel(0, chip->base + SUNXI_ALRM_DHMS); + + /* disable alarm, not generate irq pending */ + writel(0, chip->base + SUNXI_ALRM_EN); + + /* disable alarm week/cnt irq, unset to cpu */ + writel(0, chip->base + SUNXI_ALRM_IRQ_EN); + + /* clear alarm week/cnt irq pending */ + writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + + SUNXI_ALRM_IRQ_STA); + + chip->rtc = rtc_device_register("rtc-sunxi", &pdev->dev, + &sunxi_rtc_ops, THIS_MODULE); + if (IS_ERR(chip->rtc)) { + dev_err(&pdev->dev, "unable to register device\n"); + return PTR_ERR(chip->rtc); + } + + dev_info(&pdev->dev, "RTC enabled\n"); + + return 0; +} + +static int sunxi_rtc_remove(struct platform_device *pdev) +{ + struct sunxi_rtc_dev *chip = platform_get_drvdata(pdev); + + rtc_device_unregister(chip->rtc); + + return 0; +} + +static struct platform_driver sunxi_rtc_driver = { + .probe = sunxi_rtc_probe, + .remove = sunxi_rtc_remove, + .driver = { + .name = "sunxi-rtc", + .owner = THIS_MODULE, + .of_match_table = sunxi_rtc_dt_ids, + }, +}; + +module_platform_driver(sunxi_rtc_driver); + +MODULE_DESCRIPTION("sunxi RTC driver"); +MODULE_AUTHOR("Carlo Caione <carlo.caione@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 441ada489874..a3815eaed421 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1034,7 +1034,7 @@ config SERIAL_MSM_CONSOLE config SERIAL_MSM_HS tristate "MSM UART High Speed: Serial Driver" - depends on ARCH_MSM + depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50 select SERIAL_CORE help If you have a machine based on MSM family of SoCs, you diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index e4bf0e435af6..be33d2b0613b 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -39,6 +39,7 @@ #include <linux/module.h> #include <linux/mm.h> #include <linux/notifier.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/scatterlist.h> @@ -58,6 +59,23 @@ #include "sh-sci.h" +/* Offsets into the sci_port->irqs array */ +enum { + SCIx_ERI_IRQ, + SCIx_RXI_IRQ, + SCIx_TXI_IRQ, + SCIx_BRI_IRQ, + SCIx_NR_IRQS, + + SCIx_MUX_IRQ = SCIx_NR_IRQS, /* special case */ +}; + +#define SCIx_IRQ_IS_MUXED(port) \ + ((port)->irqs[SCIx_ERI_IRQ] == \ + (port)->irqs[SCIx_RXI_IRQ]) || \ + ((port)->irqs[SCIx_ERI_IRQ] && \ + ((port)->irqs[SCIx_RXI_IRQ] < 0)) + struct sci_port { struct uart_port port; @@ -1757,17 +1775,6 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, if (s->sampling_rate) return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1; - switch (s->cfg->scbrr_algo_id) { - case SCBRR_ALGO_1: - return freq / (16 * bps); - case SCBRR_ALGO_2: - return DIV_ROUND_CLOSEST(freq, 32 * bps) - 1; - case SCBRR_ALGO_3: - return freq / (8 * bps); - case SCBRR_ALGO_4: - return DIV_ROUND_CLOSEST(freq, 16 * bps) - 1; - } - /* Warn, but use a safe default */ WARN_ON(1); @@ -2105,36 +2112,27 @@ static int sci_init_single(struct platform_device *dev, port->iotype = UPIO_MEM; port->line = index; - if (dev->num_resources) { - /* Device has resources, use them. */ - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (res == NULL) - return -ENOMEM; + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (res == NULL) + return -ENOMEM; - port->mapbase = res->start; + port->mapbase = res->start; - for (i = 0; i < ARRAY_SIZE(sci_port->irqs); ++i) - sci_port->irqs[i] = platform_get_irq(dev, i); + for (i = 0; i < ARRAY_SIZE(sci_port->irqs); ++i) + sci_port->irqs[i] = platform_get_irq(dev, i); - /* The SCI generates several interrupts. They can be muxed - * together or connected to different interrupt lines. In the - * muxed case only one interrupt resource is specified. In the - * non-muxed case three or four interrupt resources are - * specified, as the BRI interrupt is optional. - */ - if (sci_port->irqs[0] < 0) - return -ENXIO; + /* The SCI generates several interrupts. They can be muxed together or + * connected to different interrupt lines. In the muxed case only one + * interrupt resource is specified. In the non-muxed case three or four + * interrupt resources are specified, as the BRI interrupt is optional. + */ + if (sci_port->irqs[0] < 0) + return -ENXIO; - if (sci_port->irqs[1] < 0) { - sci_port->irqs[1] = sci_port->irqs[0]; - sci_port->irqs[2] = sci_port->irqs[0]; - sci_port->irqs[3] = sci_port->irqs[0]; - } - } else { - /* No resources, use old-style platform data. */ - port->mapbase = p->mapbase; - for (i = 0; i < ARRAY_SIZE(sci_port->irqs); ++i) - sci_port->irqs[i] = p->irqs[i] ? p->irqs[i] : -ENXIO; + if (sci_port->irqs[1] < 0) { + sci_port->irqs[1] = sci_port->irqs[0]; + sci_port->irqs[2] = sci_port->irqs[0]; + sci_port->irqs[3] = sci_port->irqs[0]; } if (p->regtype == SCIx_PROBE_REGTYPE) { @@ -2176,17 +2174,12 @@ static int sci_init_single(struct platform_device *dev, break; } - /* Set the sampling rate if the baud rate calculation algorithm isn't - * specified. + /* SCIFA on sh7723 and sh7724 need a custom sampling rate that doesn't + * match the SoC datasheet, this should be investigated. Let platform + * data override the sampling rate for now. */ - if (p->scbrr_algo_id == SCBRR_ALGO_NONE) { - /* SCIFA on sh7723 and sh7724 need a custom sampling rate that - * doesn't match the SoC datasheet, this should be investigated. - * Let platform data override the sampling rate for now. - */ - sci_port->sampling_rate = p->sampling_rate ? p->sampling_rate - : sampling_rate; - } + sci_port->sampling_rate = p->sampling_rate ? p->sampling_rate + : sampling_rate; if (!early) { sci_port->iclk = clk_get(&dev->dev, "sci_ick"); @@ -2423,6 +2416,83 @@ static int sci_remove(struct platform_device *dev) return 0; } +struct sci_port_info { + unsigned int type; + unsigned int regtype; +}; + +static const struct of_device_id of_sci_match[] = { + { + .compatible = "renesas,scif", + .data = (void *)&(const struct sci_port_info) { + .type = PORT_SCIF, + .regtype = SCIx_SH4_SCIF_REGTYPE, + }, + }, { + .compatible = "renesas,scifa", + .data = (void *)&(const struct sci_port_info) { + .type = PORT_SCIFA, + .regtype = SCIx_SCIFA_REGTYPE, + }, + }, { + .compatible = "renesas,scifb", + .data = (void *)&(const struct sci_port_info) { + .type = PORT_SCIFB, + .regtype = SCIx_SCIFB_REGTYPE, + }, + }, { + .compatible = "renesas,hscif", + .data = (void *)&(const struct sci_port_info) { + .type = PORT_HSCIF, + .regtype = SCIx_HSCIF_REGTYPE, + }, + }, { + /* Terminator */ + }, +}; +MODULE_DEVICE_TABLE(of, of_sci_match); + +static struct plat_sci_port * +sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + const struct sci_port_info *info; + struct plat_sci_port *p; + int id; + + if (!IS_ENABLED(CONFIG_OF) || !np) + return NULL; + + match = of_match_node(of_sci_match, pdev->dev.of_node); + if (!match) + return NULL; + + info = match->data; + + p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL); + if (!p) { + dev_err(&pdev->dev, "failed to allocate DT config data\n"); + return NULL; + } + + /* Get the line number for the aliases node. */ + id = of_alias_get_id(np, "serial"); + if (id < 0) { + dev_err(&pdev->dev, "failed to get alias id (%d)\n", id); + return NULL; + } + + *dev_id = id; + + p->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; + p->type = info->type; + p->regtype = info->regtype; + p->scscr = SCSCR_RE | SCSCR_TE; + + return p; +} + static int sci_probe_single(struct platform_device *dev, unsigned int index, struct plat_sci_port *p, @@ -2455,8 +2525,9 @@ static int sci_probe_single(struct platform_device *dev, static int sci_probe(struct platform_device *dev) { - struct plat_sci_port *p = dev_get_platdata(&dev->dev); - struct sci_port *sp = &sci_ports[dev->id]; + struct plat_sci_port *p; + struct sci_port *sp; + unsigned int dev_id; int ret; /* @@ -2467,9 +2538,24 @@ static int sci_probe(struct platform_device *dev) if (is_early_platform_device(dev)) return sci_probe_earlyprintk(dev); + if (dev->dev.of_node) { + p = sci_parse_dt(dev, &dev_id); + if (p == NULL) + return -EINVAL; + } else { + p = dev->dev.platform_data; + if (p == NULL) { + dev_err(&dev->dev, "no platform data supplied\n"); + return -EINVAL; + } + + dev_id = dev->id; + } + + sp = &sci_ports[dev_id]; platform_set_drvdata(dev, sp); - ret = sci_probe_single(dev, dev->id, p, sp); + ret = sci_probe_single(dev, dev_id, p, sp); if (ret) return ret; @@ -2521,6 +2607,7 @@ static struct platform_driver sci_driver = { .name = "sh-sci", .owner = THIS_MODULE, .pm = &sci_dev_pm_ops, + .of_match_table = of_match_ptr(of_sci_match), }, }; diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index c6c325e4d80d..110b4b9ebeaa 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -94,7 +94,7 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597) int i = 0; if (r8a66597->pdata->on_chip) { - clk_enable(r8a66597->clk); + clk_prepare_enable(r8a66597->clk); do { r8a66597_write(r8a66597, SCKE, SYSCFG0); tmp = r8a66597_read(r8a66597, SYSCFG0); @@ -138,7 +138,7 @@ static void r8a66597_clock_disable(struct r8a66597 *r8a66597) udelay(1); if (r8a66597->pdata->on_chip) { - clk_disable(r8a66597->clk); + clk_disable_unprepare(r8a66597->clk); } else { r8a66597_bclr(r8a66597, PLLC, SYSCFG0); r8a66597_bclr(r8a66597, XCKE, SYSCFG0); diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 37752832b770..8546c8dccd51 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -40,8 +40,6 @@ #include <linux/usb/msm_hsusb_hw.h> #include <linux/regulator/consumer.h> -#include <mach/clk.h> - #define MSM_USB_BASE (motg->regs) #define DRIVER_NAME "msm_otg" @@ -308,33 +306,30 @@ static void ulpi_init(struct msm_otg *motg) static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert) { - int ret; + int ret = 0; + + if (!motg->pdata->link_clk_reset) + return ret; + + ret = motg->pdata->link_clk_reset(motg->clk, assert); + if (ret) + dev_err(motg->phy.dev, "usb link clk reset %s failed\n", + assert ? "assert" : "deassert"); - if (assert) { - ret = clk_reset(motg->clk, CLK_RESET_ASSERT); - if (ret) - dev_err(motg->phy.dev, "usb hs_clk assert failed\n"); - } else { - ret = clk_reset(motg->clk, CLK_RESET_DEASSERT); - if (ret) - dev_err(motg->phy.dev, "usb hs_clk deassert failed\n"); - } return ret; } static int msm_otg_phy_clk_reset(struct msm_otg *motg) { - int ret; + int ret = 0; - ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT); - if (ret) { - dev_err(motg->phy.dev, "usb phy clk assert failed\n"); + if (!motg->pdata->phy_clk_reset) return ret; - } - usleep_range(10000, 12000); - ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT); + + ret = motg->pdata->phy_clk_reset(motg->phy_reset_clk); if (ret) - dev_err(motg->phy.dev, "usb phy clk deassert failed\n"); + dev_err(motg->phy.dev, "usb phy clk reset failed\n"); + return ret; } diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index dd625cca1ae5..12591f6596ef 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c @@ -247,7 +247,7 @@ MODULE_DEVICE_TABLE(of, davinci_wdt_of_match); static struct platform_driver platform_wdt_driver = { .driver = { - .name = "watchdog", + .name = "davinci-wdt", .owner = THIS_MODULE, .of_match_table = davinci_wdt_of_match, }, @@ -267,4 +267,4 @@ MODULE_PARM_DESC(heartbeat, __MODULE_STRING(DEFAULT_HEARTBEAT)); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:watchdog"); +MODULE_ALIAS("platform:davinci-wdt"); |