hsmc.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * Static Memory Controller for AT32 chips
  3. *
  4. * Copyright (C) 2006 Atmel Corporation
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #define DEBUG
  11. #include <linux/clk.h>
  12. #include <linux/err.h>
  13. #include <linux/init.h>
  14. #include <linux/module.h>
  15. #include <linux/platform_device.h>
  16. #include <asm/io.h>
  17. #include <asm/arch/smc.h>
  18. #include "hsmc.h"
  19. #define NR_CHIP_SELECTS 6
  20. struct hsmc {
  21. void __iomem *regs;
  22. struct clk *pclk;
  23. struct clk *mck;
  24. };
  25. static struct hsmc *hsmc;
  26. int smc_set_configuration(int cs, const struct smc_config *config)
  27. {
  28. unsigned long mul;
  29. unsigned long offset;
  30. u32 setup, pulse, cycle, mode;
  31. if (!hsmc)
  32. return -ENODEV;
  33. if (cs >= NR_CHIP_SELECTS)
  34. return -EINVAL;
  35. /*
  36. * cycles = x / T = x * f
  37. * = ((x * 1000000000) * ((f * 65536) / 1000000000)) / 65536
  38. * = ((x * 1000000000) * (((f / 10000) * 65536) / 100000)) / 65536
  39. */
  40. mul = (clk_get_rate(hsmc->mck) / 10000) << 16;
  41. mul /= 100000;
  42. #define ns2cyc(x) ((((x) * mul) + 65535) >> 16)
  43. setup = (HSMC_BF(NWE_SETUP, ns2cyc(config->nwe_setup))
  44. | HSMC_BF(NCS_WR_SETUP, ns2cyc(config->ncs_write_setup))
  45. | HSMC_BF(NRD_SETUP, ns2cyc(config->nrd_setup))
  46. | HSMC_BF(NCS_RD_SETUP, ns2cyc(config->ncs_read_setup)));
  47. pulse = (HSMC_BF(NWE_PULSE, ns2cyc(config->nwe_pulse))
  48. | HSMC_BF(NCS_WR_PULSE, ns2cyc(config->ncs_write_pulse))
  49. | HSMC_BF(NRD_PULSE, ns2cyc(config->nrd_pulse))
  50. | HSMC_BF(NCS_RD_PULSE, ns2cyc(config->ncs_read_pulse)));
  51. cycle = (HSMC_BF(NWE_CYCLE, ns2cyc(config->write_cycle))
  52. | HSMC_BF(NRD_CYCLE, ns2cyc(config->read_cycle)));
  53. switch (config->bus_width) {
  54. case 1:
  55. mode = HSMC_BF(DBW, HSMC_DBW_8_BITS);
  56. break;
  57. case 2:
  58. mode = HSMC_BF(DBW, HSMC_DBW_16_BITS);
  59. break;
  60. case 4:
  61. mode = HSMC_BF(DBW, HSMC_DBW_32_BITS);
  62. break;
  63. default:
  64. return -EINVAL;
  65. }
  66. if (config->nrd_controlled)
  67. mode |= HSMC_BIT(READ_MODE);
  68. if (config->nwe_controlled)
  69. mode |= HSMC_BIT(WRITE_MODE);
  70. if (config->byte_write)
  71. mode |= HSMC_BIT(BAT);
  72. pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n",
  73. cs, setup, pulse, cycle, mode);
  74. offset = cs * 0x10;
  75. hsmc_writel(hsmc, SETUP0 + offset, setup);
  76. hsmc_writel(hsmc, PULSE0 + offset, pulse);
  77. hsmc_writel(hsmc, CYCLE0 + offset, cycle);
  78. hsmc_writel(hsmc, MODE0 + offset, mode);
  79. hsmc_readl(hsmc, MODE0); /* I/O barrier */
  80. return 0;
  81. }
  82. EXPORT_SYMBOL(smc_set_configuration);
  83. static int hsmc_probe(struct platform_device *pdev)
  84. {
  85. struct resource *regs;
  86. struct clk *pclk, *mck;
  87. int ret;
  88. if (hsmc)
  89. return -EBUSY;
  90. regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  91. if (!regs)
  92. return -ENXIO;
  93. pclk = clk_get(&pdev->dev, "pclk");
  94. if (IS_ERR(pclk))
  95. return PTR_ERR(pclk);
  96. mck = clk_get(&pdev->dev, "mck");
  97. if (IS_ERR(mck)) {
  98. ret = PTR_ERR(mck);
  99. goto out_put_pclk;
  100. }
  101. ret = -ENOMEM;
  102. hsmc = kzalloc(sizeof(struct hsmc), GFP_KERNEL);
  103. if (!hsmc)
  104. goto out_put_clocks;
  105. clk_enable(pclk);
  106. clk_enable(mck);
  107. hsmc->pclk = pclk;
  108. hsmc->mck = mck;
  109. hsmc->regs = ioremap(regs->start, regs->end - regs->start + 1);
  110. if (!hsmc->regs)
  111. goto out_disable_clocks;
  112. dev_info(&pdev->dev, "Atmel Static Memory Controller at 0x%08lx\n",
  113. (unsigned long)regs->start);
  114. platform_set_drvdata(pdev, hsmc);
  115. return 0;
  116. out_disable_clocks:
  117. clk_disable(mck);
  118. clk_disable(pclk);
  119. kfree(hsmc);
  120. out_put_clocks:
  121. clk_put(mck);
  122. out_put_pclk:
  123. clk_put(pclk);
  124. hsmc = NULL;
  125. return ret;
  126. }
  127. static struct platform_driver hsmc_driver = {
  128. .probe = hsmc_probe,
  129. .driver = {
  130. .name = "smc",
  131. },
  132. };
  133. static int __init hsmc_init(void)
  134. {
  135. return platform_driver_register(&hsmc_driver);
  136. }
  137. arch_initcall(hsmc_init);