diff options
author | Ladislav Michl <ladis@linux-mips.org> | 2018-01-12 08:17:25 -0500 |
---|---|---|
committer | Boris Brezillon <boris.brezillon@free-electrons.com> | 2018-01-12 10:41:15 -0500 |
commit | a758f50f10cfcf863f95372ff52e0d8d22fda9ba (patch) | |
tree | 294a2badeec6d690b68db82d8dbd29637c6edec7 /drivers/memory | |
parent | bdaca9345d41fd9420995469d27603ea62054691 (diff) |
mtd: onenand: omap2: Configure driver from DT
Move away from platform data configuration and use pure DT approach.
Use generic probe function to deal with OneNAND node and remove now useless
gpmc_probe_onenand_child function. Import sync mode timing calculation
function from mach-omap2/gpmc-onenand.c
Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
Reviewed-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Acked-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Diffstat (limited to 'drivers/memory')
-rw-r--r-- | drivers/memory/omap-gpmc.c | 158 |
1 files changed, 117 insertions, 41 deletions
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 0e30ee1c8677..90a66b3f7ae1 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
33 | 33 | ||
34 | #include <linux/platform_data/mtd-nand-omap2.h> | 34 | #include <linux/platform_data/mtd-nand-omap2.h> |
35 | #include <linux/platform_data/mtd-onenand-omap2.h> | ||
36 | 35 | ||
37 | #include <asm/mach-types.h> | 36 | #include <asm/mach-types.h> |
38 | 37 | ||
@@ -1138,6 +1137,112 @@ struct gpmc_nand_ops *gpmc_omap_get_nand_ops(struct gpmc_nand_regs *reg, int cs) | |||
1138 | } | 1137 | } |
1139 | EXPORT_SYMBOL_GPL(gpmc_omap_get_nand_ops); | 1138 | EXPORT_SYMBOL_GPL(gpmc_omap_get_nand_ops); |
1140 | 1139 | ||
1140 | static void gpmc_omap_onenand_calc_sync_timings(struct gpmc_timings *t, | ||
1141 | struct gpmc_settings *s, | ||
1142 | int freq, int latency) | ||
1143 | { | ||
1144 | struct gpmc_device_timings dev_t; | ||
1145 | const int t_cer = 15; | ||
1146 | const int t_avdp = 12; | ||
1147 | const int t_cez = 20; /* max of t_cez, t_oez */ | ||
1148 | const int t_wpl = 40; | ||
1149 | const int t_wph = 30; | ||
1150 | int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; | ||
1151 | |||
1152 | switch (freq) { | ||
1153 | case 104: | ||
1154 | min_gpmc_clk_period = 9600; /* 104 MHz */ | ||
1155 | t_ces = 3; | ||
1156 | t_avds = 4; | ||
1157 | t_avdh = 2; | ||
1158 | t_ach = 3; | ||
1159 | t_aavdh = 6; | ||
1160 | t_rdyo = 6; | ||
1161 | break; | ||
1162 | case 83: | ||
1163 | min_gpmc_clk_period = 12000; /* 83 MHz */ | ||
1164 | t_ces = 5; | ||
1165 | t_avds = 4; | ||
1166 | t_avdh = 2; | ||
1167 | t_ach = 6; | ||
1168 | t_aavdh = 6; | ||
1169 | t_rdyo = 9; | ||
1170 | break; | ||
1171 | case 66: | ||
1172 | min_gpmc_clk_period = 15000; /* 66 MHz */ | ||
1173 | t_ces = 6; | ||
1174 | t_avds = 5; | ||
1175 | t_avdh = 2; | ||
1176 | t_ach = 6; | ||
1177 | t_aavdh = 6; | ||
1178 | t_rdyo = 11; | ||
1179 | break; | ||
1180 | default: | ||
1181 | min_gpmc_clk_period = 18500; /* 54 MHz */ | ||
1182 | t_ces = 7; | ||
1183 | t_avds = 7; | ||
1184 | t_avdh = 7; | ||
1185 | t_ach = 9; | ||
1186 | t_aavdh = 7; | ||
1187 | t_rdyo = 15; | ||
1188 | break; | ||
1189 | } | ||
1190 | |||
1191 | /* Set synchronous read timings */ | ||
1192 | memset(&dev_t, 0, sizeof(dev_t)); | ||
1193 | |||
1194 | if (!s->sync_write) { | ||
1195 | dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000; | ||
1196 | dev_t.t_wpl = t_wpl * 1000; | ||
1197 | dev_t.t_wph = t_wph * 1000; | ||
1198 | dev_t.t_aavdh = t_aavdh * 1000; | ||
1199 | } | ||
1200 | dev_t.ce_xdelay = true; | ||
1201 | dev_t.avd_xdelay = true; | ||
1202 | dev_t.oe_xdelay = true; | ||
1203 | dev_t.we_xdelay = true; | ||
1204 | dev_t.clk = min_gpmc_clk_period; | ||
1205 | dev_t.t_bacc = dev_t.clk; | ||
1206 | dev_t.t_ces = t_ces * 1000; | ||
1207 | dev_t.t_avds = t_avds * 1000; | ||
1208 | dev_t.t_avdh = t_avdh * 1000; | ||
1209 | dev_t.t_ach = t_ach * 1000; | ||
1210 | dev_t.cyc_iaa = (latency + 1); | ||
1211 | dev_t.t_cez_r = t_cez * 1000; | ||
1212 | dev_t.t_cez_w = dev_t.t_cez_r; | ||
1213 | dev_t.cyc_aavdh_oe = 1; | ||
1214 | dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period; | ||
1215 | |||
1216 | gpmc_calc_timings(t, s, &dev_t); | ||
1217 | } | ||
1218 | |||
1219 | int gpmc_omap_onenand_set_timings(struct device *dev, int cs, int freq, | ||
1220 | int latency, | ||
1221 | struct gpmc_onenand_info *info) | ||
1222 | { | ||
1223 | int ret; | ||
1224 | struct gpmc_timings gpmc_t; | ||
1225 | struct gpmc_settings gpmc_s; | ||
1226 | |||
1227 | gpmc_read_settings_dt(dev->of_node, &gpmc_s); | ||
1228 | |||
1229 | info->sync_read = gpmc_s.sync_read; | ||
1230 | info->sync_write = gpmc_s.sync_write; | ||
1231 | info->burst_len = gpmc_s.burst_len; | ||
1232 | |||
1233 | if (!gpmc_s.sync_read && !gpmc_s.sync_write) | ||
1234 | return 0; | ||
1235 | |||
1236 | gpmc_omap_onenand_calc_sync_timings(&gpmc_t, &gpmc_s, freq, latency); | ||
1237 | |||
1238 | ret = gpmc_cs_program_settings(cs, &gpmc_s); | ||
1239 | if (ret < 0) | ||
1240 | return ret; | ||
1241 | |||
1242 | return gpmc_cs_set_timings(cs, &gpmc_t, &gpmc_s); | ||
1243 | } | ||
1244 | EXPORT_SYMBOL_GPL(gpmc_omap_onenand_set_timings); | ||
1245 | |||
1141 | int gpmc_get_client_irq(unsigned irq_config) | 1246 | int gpmc_get_client_irq(unsigned irq_config) |
1142 | { | 1247 | { |
1143 | if (!gpmc_irq_domain) { | 1248 | if (!gpmc_irq_domain) { |
@@ -1916,41 +2021,6 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np, | |||
1916 | of_property_read_bool(np, "gpmc,time-para-granularity"); | 2021 | of_property_read_bool(np, "gpmc,time-para-granularity"); |
1917 | } | 2022 | } |
1918 | 2023 | ||
1919 | #if IS_ENABLED(CONFIG_MTD_ONENAND) | ||
1920 | static int gpmc_probe_onenand_child(struct platform_device *pdev, | ||
1921 | struct device_node *child) | ||
1922 | { | ||
1923 | u32 val; | ||
1924 | struct omap_onenand_platform_data *gpmc_onenand_data; | ||
1925 | |||
1926 | if (of_property_read_u32(child, "reg", &val) < 0) { | ||
1927 | dev_err(&pdev->dev, "%pOF has no 'reg' property\n", | ||
1928 | child); | ||
1929 | return -ENODEV; | ||
1930 | } | ||
1931 | |||
1932 | gpmc_onenand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_onenand_data), | ||
1933 | GFP_KERNEL); | ||
1934 | if (!gpmc_onenand_data) | ||
1935 | return -ENOMEM; | ||
1936 | |||
1937 | gpmc_onenand_data->cs = val; | ||
1938 | gpmc_onenand_data->of_node = child; | ||
1939 | gpmc_onenand_data->dma_channel = -1; | ||
1940 | |||
1941 | if (!of_property_read_u32(child, "dma-channel", &val)) | ||
1942 | gpmc_onenand_data->dma_channel = val; | ||
1943 | |||
1944 | return gpmc_onenand_init(gpmc_onenand_data); | ||
1945 | } | ||
1946 | #else | ||
1947 | static int gpmc_probe_onenand_child(struct platform_device *pdev, | ||
1948 | struct device_node *child) | ||
1949 | { | ||
1950 | return 0; | ||
1951 | } | ||
1952 | #endif | ||
1953 | |||
1954 | /** | 2024 | /** |
1955 | * gpmc_probe_generic_child - configures the gpmc for a child device | 2025 | * gpmc_probe_generic_child - configures the gpmc for a child device |
1956 | * @pdev: pointer to gpmc platform device | 2026 | * @pdev: pointer to gpmc platform device |
@@ -2053,6 +2123,16 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, | |||
2053 | } | 2123 | } |
2054 | } | 2124 | } |
2055 | 2125 | ||
2126 | if (of_node_cmp(child->name, "onenand") == 0) { | ||
2127 | /* Warn about older DT blobs with no compatible property */ | ||
2128 | if (!of_property_read_bool(child, "compatible")) { | ||
2129 | dev_warn(&pdev->dev, | ||
2130 | "Incompatible OneNAND node: missing compatible"); | ||
2131 | ret = -EINVAL; | ||
2132 | goto err; | ||
2133 | } | ||
2134 | } | ||
2135 | |||
2056 | if (of_device_is_compatible(child, "ti,omap2-nand")) { | 2136 | if (of_device_is_compatible(child, "ti,omap2-nand")) { |
2057 | /* NAND specific setup */ | 2137 | /* NAND specific setup */ |
2058 | val = 8; | 2138 | val = 8; |
@@ -2189,11 +2269,7 @@ static void gpmc_probe_dt_children(struct platform_device *pdev) | |||
2189 | if (!child->name) | 2269 | if (!child->name) |
2190 | continue; | 2270 | continue; |
2191 | 2271 | ||
2192 | if (of_node_cmp(child->name, "onenand") == 0) | 2272 | ret = gpmc_probe_generic_child(pdev, child); |
2193 | ret = gpmc_probe_onenand_child(pdev, child); | ||
2194 | else | ||
2195 | ret = gpmc_probe_generic_child(pdev, child); | ||
2196 | |||
2197 | if (ret) { | 2273 | if (ret) { |
2198 | dev_err(&pdev->dev, "failed to probe DT child '%s': %d\n", | 2274 | dev_err(&pdev->dev, "failed to probe DT child '%s': %d\n", |
2199 | child->name, ret); | 2275 | child->name, ret); |