|
@@ -1106,3 +1106,131 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
|
|
|
gpmc_calc_common_timings(gpmc_t, dev_t);
|
|
|
|
|
|
if (dev_t->sync_read)
|
|
|
+ gpmc_calc_sync_read_timings(gpmc_t, dev_t);
|
|
|
+ else
|
|
|
+ gpmc_calc_async_read_timings(gpmc_t, dev_t);
|
|
|
+
|
|
|
+ if (dev_t->sync_write)
|
|
|
+ gpmc_calc_sync_write_timings(gpmc_t, dev_t);
|
|
|
+ else
|
|
|
+ gpmc_calc_async_write_timings(gpmc_t, dev_t);
|
|
|
+
|
|
|
+ /* TODO: remove, see function definition */
|
|
|
+ gpmc_convert_ps_to_ns(gpmc_t);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int gpmc_probe(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ int rc;
|
|
|
+ u32 l;
|
|
|
+ struct resource *res;
|
|
|
+
|
|
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
+ if (res == NULL)
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
+ phys_base = res->start;
|
|
|
+ mem_size = resource_size(res);
|
|
|
+
|
|
|
+ gpmc_base = devm_request_and_ioremap(&pdev->dev, res);
|
|
|
+ if (!gpmc_base) {
|
|
|
+ dev_err(&pdev->dev, "error: request memory / ioremap\n");
|
|
|
+ return -EADDRNOTAVAIL;
|
|
|
+ }
|
|
|
+
|
|
|
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
|
|
+ if (res == NULL)
|
|
|
+ dev_warn(&pdev->dev, "Failed to get resource: irq\n");
|
|
|
+ else
|
|
|
+ gpmc_irq = res->start;
|
|
|
+
|
|
|
+ gpmc_l3_clk = clk_get(&pdev->dev, "fck");
|
|
|
+ if (IS_ERR(gpmc_l3_clk)) {
|
|
|
+ dev_err(&pdev->dev, "error: clk_get\n");
|
|
|
+ gpmc_irq = 0;
|
|
|
+ return PTR_ERR(gpmc_l3_clk);
|
|
|
+ }
|
|
|
+
|
|
|
+ clk_prepare_enable(gpmc_l3_clk);
|
|
|
+
|
|
|
+ gpmc_dev = &pdev->dev;
|
|
|
+
|
|
|
+ l = gpmc_read_reg(GPMC_REVISION);
|
|
|
+ if (GPMC_REVISION_MAJOR(l) > 0x4)
|
|
|
+ gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS;
|
|
|
+ dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
|
|
|
+ GPMC_REVISION_MINOR(l));
|
|
|
+
|
|
|
+ rc = gpmc_mem_init();
|
|
|
+ if (IS_ERR_VALUE(rc)) {
|
|
|
+ clk_disable_unprepare(gpmc_l3_clk);
|
|
|
+ clk_put(gpmc_l3_clk);
|
|
|
+ dev_err(gpmc_dev, "failed to reserve memory\n");
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (IS_ERR_VALUE(gpmc_setup_irq()))
|
|
|
+ dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int gpmc_remove(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ gpmc_free_irq();
|
|
|
+ gpmc_mem_exit();
|
|
|
+ gpmc_dev = NULL;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct platform_driver gpmc_driver = {
|
|
|
+ .probe = gpmc_probe,
|
|
|
+ .remove = gpmc_remove,
|
|
|
+ .driver = {
|
|
|
+ .name = DEVICE_NAME,
|
|
|
+ .owner = THIS_MODULE,
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+static __init int gpmc_init(void)
|
|
|
+{
|
|
|
+ return platform_driver_register(&gpmc_driver);
|
|
|
+}
|
|
|
+
|
|
|
+static __exit void gpmc_exit(void)
|
|
|
+{
|
|
|
+ platform_driver_unregister(&gpmc_driver);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+postcore_initcall(gpmc_init);
|
|
|
+module_exit(gpmc_exit);
|
|
|
+
|
|
|
+static int __init omap_gpmc_init(void)
|
|
|
+{
|
|
|
+ struct omap_hwmod *oh;
|
|
|
+ struct platform_device *pdev;
|
|
|
+ char *oh_name = "gpmc";
|
|
|
+
|
|
|
+ oh = omap_hwmod_lookup(oh_name);
|
|
|
+ if (!oh) {
|
|
|
+ pr_err("Could not look up %s\n", oh_name);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
+ pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0, NULL, 0, 0);
|
|
|
+ WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
|
|
|
+
|
|
|
+ return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
|
|
|
+}
|
|
|
+postcore_initcall(omap_gpmc_init);
|
|
|
+
|
|
|
+static irqreturn_t gpmc_handle_irq(int irq, void *dev)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ u32 regval;
|
|
|
+
|
|
|
+ regval = gpmc_read_reg(GPMC_IRQSTATUS);
|
|
|
+
|