2 * NAND Flash Controller Device Driver for DT
4 * Copyright © 2011, Picochip.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 #include <linux/clk.h>
16 #include <linux/err.h>
18 #include <linux/ioport.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/platform_device.h>
23 #include <linux/of_device.h>
28 struct denali_nand_info denali
;
32 struct denali_dt_data
{
33 unsigned int revision
;
35 const struct nand_ecc_caps
*ecc_caps
;
38 NAND_ECC_CAPS_SINGLE(denali_socfpga_ecc_caps
, denali_calc_ecc_bytes
,
40 static const struct denali_dt_data denali_socfpga_data
= {
41 .caps
= DENALI_CAP_HW_ECC_FIXUP
,
42 .ecc_caps
= &denali_socfpga_ecc_caps
,
45 NAND_ECC_CAPS_SINGLE(denali_uniphier_v5a_ecc_caps
, denali_calc_ecc_bytes
,
47 static const struct denali_dt_data denali_uniphier_v5a_data
= {
48 .caps
= DENALI_CAP_HW_ECC_FIXUP
|
50 .ecc_caps
= &denali_uniphier_v5a_ecc_caps
,
53 NAND_ECC_CAPS_SINGLE(denali_uniphier_v5b_ecc_caps
, denali_calc_ecc_bytes
,
55 static const struct denali_dt_data denali_uniphier_v5b_data
= {
57 .caps
= DENALI_CAP_HW_ECC_FIXUP
|
59 .ecc_caps
= &denali_uniphier_v5b_ecc_caps
,
62 static const struct of_device_id denali_nand_dt_ids
[] = {
64 .compatible
= "altr,socfpga-denali-nand",
65 .data
= &denali_socfpga_data
,
68 .compatible
= "socionext,uniphier-denali-nand-v5a",
69 .data
= &denali_uniphier_v5a_data
,
72 .compatible
= "socionext,uniphier-denali-nand-v5b",
73 .data
= &denali_uniphier_v5b_data
,
77 MODULE_DEVICE_TABLE(of
, denali_nand_dt_ids
);
79 static int denali_dt_probe(struct platform_device
*pdev
)
83 const struct denali_dt_data
*data
;
84 struct denali_nand_info
*denali
;
87 dt
= devm_kzalloc(&pdev
->dev
, sizeof(*dt
), GFP_KERNEL
);
92 data
= of_device_get_match_data(&pdev
->dev
);
94 denali
->revision
= data
->revision
;
95 denali
->caps
= data
->caps
;
96 denali
->ecc_caps
= data
->ecc_caps
;
99 denali
->dev
= &pdev
->dev
;
100 denali
->irq
= platform_get_irq(pdev
, 0);
101 if (denali
->irq
< 0) {
102 dev_err(&pdev
->dev
, "no irq defined\n");
106 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "denali_reg");
107 denali
->reg
= devm_ioremap_resource(&pdev
->dev
, res
);
108 if (IS_ERR(denali
->reg
))
109 return PTR_ERR(denali
->reg
);
111 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "nand_data");
112 denali
->host
= devm_ioremap_resource(&pdev
->dev
, res
);
113 if (IS_ERR(denali
->host
))
114 return PTR_ERR(denali
->host
);
116 dt
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
117 if (IS_ERR(dt
->clk
)) {
118 dev_err(&pdev
->dev
, "no clk available\n");
119 return PTR_ERR(dt
->clk
);
121 clk_prepare_enable(dt
->clk
);
123 denali
->clk_x_rate
= clk_get_rate(dt
->clk
);
125 ret
= denali_init(denali
);
127 goto out_disable_clk
;
129 platform_set_drvdata(pdev
, dt
);
133 clk_disable_unprepare(dt
->clk
);
138 static int denali_dt_remove(struct platform_device
*pdev
)
140 struct denali_dt
*dt
= platform_get_drvdata(pdev
);
142 denali_remove(&dt
->denali
);
143 clk_disable_unprepare(dt
->clk
);
148 static struct platform_driver denali_dt_driver
= {
149 .probe
= denali_dt_probe
,
150 .remove
= denali_dt_remove
,
152 .name
= "denali-nand-dt",
153 .of_match_table
= denali_nand_dt_ids
,
157 module_platform_driver(denali_dt_driver
);
159 MODULE_LICENSE("GPL");
160 MODULE_AUTHOR("Jamie Iles");
161 MODULE_DESCRIPTION("DT driver for Denali NAND controller");