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
16 #include <linux/clk.h>
17 #include <linux/err.h>
19 #include <linux/ioport.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
23 #include <linux/of_device.h>
24 #include <linux/platform_device.h>
29 struct denali_nand_info denali
;
33 struct denali_dt_data
{
34 unsigned int revision
;
36 const struct nand_ecc_caps
*ecc_caps
;
39 NAND_ECC_CAPS_SINGLE(denali_socfpga_ecc_caps
, denali_calc_ecc_bytes
,
41 static const struct denali_dt_data denali_socfpga_data
= {
42 .caps
= DENALI_CAP_HW_ECC_FIXUP
,
43 .ecc_caps
= &denali_socfpga_ecc_caps
,
46 NAND_ECC_CAPS_SINGLE(denali_uniphier_v5a_ecc_caps
, denali_calc_ecc_bytes
,
48 static const struct denali_dt_data denali_uniphier_v5a_data
= {
49 .caps
= DENALI_CAP_HW_ECC_FIXUP
|
51 .ecc_caps
= &denali_uniphier_v5a_ecc_caps
,
54 NAND_ECC_CAPS_SINGLE(denali_uniphier_v5b_ecc_caps
, denali_calc_ecc_bytes
,
56 static const struct denali_dt_data denali_uniphier_v5b_data
= {
58 .caps
= DENALI_CAP_HW_ECC_FIXUP
|
60 .ecc_caps
= &denali_uniphier_v5b_ecc_caps
,
63 static const struct of_device_id denali_nand_dt_ids
[] = {
65 .compatible
= "altr,socfpga-denali-nand",
66 .data
= &denali_socfpga_data
,
69 .compatible
= "socionext,uniphier-denali-nand-v5a",
70 .data
= &denali_uniphier_v5a_data
,
73 .compatible
= "socionext,uniphier-denali-nand-v5b",
74 .data
= &denali_uniphier_v5b_data
,
78 MODULE_DEVICE_TABLE(of
, denali_nand_dt_ids
);
80 static int denali_dt_probe(struct platform_device
*pdev
)
84 const struct denali_dt_data
*data
;
85 struct denali_nand_info
*denali
;
88 dt
= devm_kzalloc(&pdev
->dev
, sizeof(*dt
), GFP_KERNEL
);
93 data
= of_device_get_match_data(&pdev
->dev
);
95 denali
->revision
= data
->revision
;
96 denali
->caps
= data
->caps
;
97 denali
->ecc_caps
= data
->ecc_caps
;
100 denali
->dev
= &pdev
->dev
;
101 denali
->irq
= platform_get_irq(pdev
, 0);
102 if (denali
->irq
< 0) {
103 dev_err(&pdev
->dev
, "no irq defined\n");
107 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "denali_reg");
108 denali
->reg
= devm_ioremap_resource(&pdev
->dev
, res
);
109 if (IS_ERR(denali
->reg
))
110 return PTR_ERR(denali
->reg
);
112 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "nand_data");
113 denali
->host
= devm_ioremap_resource(&pdev
->dev
, res
);
114 if (IS_ERR(denali
->host
))
115 return PTR_ERR(denali
->host
);
117 dt
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
118 if (IS_ERR(dt
->clk
)) {
119 dev_err(&pdev
->dev
, "no clk available\n");
120 return PTR_ERR(dt
->clk
);
122 ret
= clk_prepare_enable(dt
->clk
);
126 denali
->clk_x_rate
= clk_get_rate(dt
->clk
);
128 ret
= denali_init(denali
);
130 goto out_disable_clk
;
132 platform_set_drvdata(pdev
, dt
);
136 clk_disable_unprepare(dt
->clk
);
141 static int denali_dt_remove(struct platform_device
*pdev
)
143 struct denali_dt
*dt
= platform_get_drvdata(pdev
);
145 denali_remove(&dt
->denali
);
146 clk_disable_unprepare(dt
->clk
);
151 static struct platform_driver denali_dt_driver
= {
152 .probe
= denali_dt_probe
,
153 .remove
= denali_dt_remove
,
155 .name
= "denali-nand-dt",
156 .of_match_table
= denali_nand_dt_ids
,
159 module_platform_driver(denali_dt_driver
);
161 MODULE_LICENSE("GPL");
162 MODULE_AUTHOR("Jamie Iles");
163 MODULE_DESCRIPTION("DT driver for Denali NAND controller");