18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Atmel (Multi-port DDR-)SDRAM Controller driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Alexandre Belloni <alexandre.belloni@free-electrons.com> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2014 Atmel 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/clk.h> 118c2ecf20Sopenharmony_ci#include <linux/err.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 158c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistruct at91_ramc_caps { 188c2ecf20Sopenharmony_ci bool has_ddrck; 198c2ecf20Sopenharmony_ci bool has_mpddr_clk; 208c2ecf20Sopenharmony_ci}; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic const struct at91_ramc_caps at91rm9200_caps = { }; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic const struct at91_ramc_caps at91sam9g45_caps = { 258c2ecf20Sopenharmony_ci .has_ddrck = 1, 268c2ecf20Sopenharmony_ci .has_mpddr_clk = 0, 278c2ecf20Sopenharmony_ci}; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic const struct at91_ramc_caps sama5d3_caps = { 308c2ecf20Sopenharmony_ci .has_ddrck = 1, 318c2ecf20Sopenharmony_ci .has_mpddr_clk = 1, 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic const struct of_device_id atmel_ramc_of_match[] = { 358c2ecf20Sopenharmony_ci { .compatible = "atmel,at91rm9200-sdramc", .data = &at91rm9200_caps, }, 368c2ecf20Sopenharmony_ci { .compatible = "atmel,at91sam9260-sdramc", .data = &at91rm9200_caps, }, 378c2ecf20Sopenharmony_ci { .compatible = "atmel,at91sam9g45-ddramc", .data = &at91sam9g45_caps, }, 388c2ecf20Sopenharmony_ci { .compatible = "atmel,sama5d3-ddramc", .data = &sama5d3_caps, }, 398c2ecf20Sopenharmony_ci {}, 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic int atmel_ramc_probe(struct platform_device *pdev) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci const struct at91_ramc_caps *caps; 458c2ecf20Sopenharmony_ci struct clk *clk; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci caps = of_device_get_match_data(&pdev->dev); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci if (caps->has_ddrck) { 508c2ecf20Sopenharmony_ci clk = devm_clk_get_enabled(&pdev->dev, "ddrck"); 518c2ecf20Sopenharmony_ci if (IS_ERR(clk)) 528c2ecf20Sopenharmony_ci return PTR_ERR(clk); 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (caps->has_mpddr_clk) { 568c2ecf20Sopenharmony_ci clk = devm_clk_get_enabled(&pdev->dev, "mpddr"); 578c2ecf20Sopenharmony_ci if (IS_ERR(clk)) { 588c2ecf20Sopenharmony_ci pr_err("AT91 RAMC: couldn't get mpddr clock\n"); 598c2ecf20Sopenharmony_ci return PTR_ERR(clk); 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci return 0; 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic struct platform_driver atmel_ramc_driver = { 678c2ecf20Sopenharmony_ci .probe = atmel_ramc_probe, 688c2ecf20Sopenharmony_ci .driver = { 698c2ecf20Sopenharmony_ci .name = "atmel-ramc", 708c2ecf20Sopenharmony_ci .of_match_table = atmel_ramc_of_match, 718c2ecf20Sopenharmony_ci }, 728c2ecf20Sopenharmony_ci}; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cibuiltin_platform_driver(atmel_ramc_driver); 75