0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/clk.h>
0013 #include <linux/err.h>
0014 #include <linux/io.h>
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017 #include <linux/of.h>
0018 #include <linux/of_platform.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/platform_data/ti-aemif.h>
0021
0022 #define TA_SHIFT 2
0023 #define RHOLD_SHIFT 4
0024 #define RSTROBE_SHIFT 7
0025 #define RSETUP_SHIFT 13
0026 #define WHOLD_SHIFT 17
0027 #define WSTROBE_SHIFT 20
0028 #define WSETUP_SHIFT 26
0029 #define EW_SHIFT 30
0030 #define SSTROBE_SHIFT 31
0031
0032 #define TA(x) ((x) << TA_SHIFT)
0033 #define RHOLD(x) ((x) << RHOLD_SHIFT)
0034 #define RSTROBE(x) ((x) << RSTROBE_SHIFT)
0035 #define RSETUP(x) ((x) << RSETUP_SHIFT)
0036 #define WHOLD(x) ((x) << WHOLD_SHIFT)
0037 #define WSTROBE(x) ((x) << WSTROBE_SHIFT)
0038 #define WSETUP(x) ((x) << WSETUP_SHIFT)
0039 #define EW(x) ((x) << EW_SHIFT)
0040 #define SSTROBE(x) ((x) << SSTROBE_SHIFT)
0041
0042 #define ASIZE_MAX 0x1
0043 #define TA_MAX 0x3
0044 #define RHOLD_MAX 0x7
0045 #define RSTROBE_MAX 0x3f
0046 #define RSETUP_MAX 0xf
0047 #define WHOLD_MAX 0x7
0048 #define WSTROBE_MAX 0x3f
0049 #define WSETUP_MAX 0xf
0050 #define EW_MAX 0x1
0051 #define SSTROBE_MAX 0x1
0052 #define NUM_CS 4
0053
0054 #define TA_VAL(x) (((x) & TA(TA_MAX)) >> TA_SHIFT)
0055 #define RHOLD_VAL(x) (((x) & RHOLD(RHOLD_MAX)) >> RHOLD_SHIFT)
0056 #define RSTROBE_VAL(x) (((x) & RSTROBE(RSTROBE_MAX)) >> RSTROBE_SHIFT)
0057 #define RSETUP_VAL(x) (((x) & RSETUP(RSETUP_MAX)) >> RSETUP_SHIFT)
0058 #define WHOLD_VAL(x) (((x) & WHOLD(WHOLD_MAX)) >> WHOLD_SHIFT)
0059 #define WSTROBE_VAL(x) (((x) & WSTROBE(WSTROBE_MAX)) >> WSTROBE_SHIFT)
0060 #define WSETUP_VAL(x) (((x) & WSETUP(WSETUP_MAX)) >> WSETUP_SHIFT)
0061 #define EW_VAL(x) (((x) & EW(EW_MAX)) >> EW_SHIFT)
0062 #define SSTROBE_VAL(x) (((x) & SSTROBE(SSTROBE_MAX)) >> SSTROBE_SHIFT)
0063
0064 #define NRCSR_OFFSET 0x00
0065 #define AWCCR_OFFSET 0x04
0066 #define A1CR_OFFSET 0x10
0067
0068 #define ACR_ASIZE_MASK 0x3
0069 #define ACR_EW_MASK BIT(30)
0070 #define ACR_SSTROBE_MASK BIT(31)
0071 #define ASIZE_16BIT 1
0072
0073 #define CONFIG_MASK (TA(TA_MAX) | \
0074 RHOLD(RHOLD_MAX) | \
0075 RSTROBE(RSTROBE_MAX) | \
0076 RSETUP(RSETUP_MAX) | \
0077 WHOLD(WHOLD_MAX) | \
0078 WSTROBE(WSTROBE_MAX) | \
0079 WSETUP(WSETUP_MAX) | \
0080 EW(EW_MAX) | SSTROBE(SSTROBE_MAX) | \
0081 ASIZE_MAX)
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 struct aemif_cs_data {
0098 u8 cs;
0099 u16 wstrobe;
0100 u16 rstrobe;
0101 u8 wsetup;
0102 u8 whold;
0103 u8 rsetup;
0104 u8 rhold;
0105 u8 ta;
0106 u8 enable_ss;
0107 u8 enable_ew;
0108 u8 asize;
0109 };
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 struct aemif_device {
0121 void __iomem *base;
0122 struct clk *clk;
0123 unsigned long clk_rate;
0124 u8 num_cs;
0125 int cs_offset;
0126 struct aemif_cs_data cs_data[NUM_CS];
0127 };
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 static int aemif_calc_rate(struct platform_device *pdev, int wanted,
0140 unsigned long clk, int max)
0141 {
0142 int result;
0143
0144 result = DIV_ROUND_UP((wanted * clk), NSEC_PER_MSEC) - 1;
0145
0146 dev_dbg(&pdev->dev, "%s: result %d from %ld, %d\n", __func__, result,
0147 clk, wanted);
0148
0149
0150 if (result < 0)
0151 result = 0;
0152
0153
0154 else if (result > max)
0155 result = -EINVAL;
0156
0157 return result;
0158 }
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 static int aemif_config_abus(struct platform_device *pdev, int csnum)
0175 {
0176 struct aemif_device *aemif = platform_get_drvdata(pdev);
0177 struct aemif_cs_data *data = &aemif->cs_data[csnum];
0178 int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
0179 unsigned long clk_rate = aemif->clk_rate;
0180 unsigned offset;
0181 u32 set, val;
0182
0183 offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4;
0184
0185 ta = aemif_calc_rate(pdev, data->ta, clk_rate, TA_MAX);
0186 rhold = aemif_calc_rate(pdev, data->rhold, clk_rate, RHOLD_MAX);
0187 rstrobe = aemif_calc_rate(pdev, data->rstrobe, clk_rate, RSTROBE_MAX);
0188 rsetup = aemif_calc_rate(pdev, data->rsetup, clk_rate, RSETUP_MAX);
0189 whold = aemif_calc_rate(pdev, data->whold, clk_rate, WHOLD_MAX);
0190 wstrobe = aemif_calc_rate(pdev, data->wstrobe, clk_rate, WSTROBE_MAX);
0191 wsetup = aemif_calc_rate(pdev, data->wsetup, clk_rate, WSETUP_MAX);
0192
0193 if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 ||
0194 whold < 0 || wstrobe < 0 || wsetup < 0) {
0195 dev_err(&pdev->dev, "%s: cannot get suitable timings\n",
0196 __func__);
0197 return -EINVAL;
0198 }
0199
0200 set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) |
0201 WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup);
0202
0203 set |= (data->asize & ACR_ASIZE_MASK);
0204 if (data->enable_ew)
0205 set |= ACR_EW_MASK;
0206 if (data->enable_ss)
0207 set |= ACR_SSTROBE_MASK;
0208
0209 val = readl(aemif->base + offset);
0210 val &= ~CONFIG_MASK;
0211 val |= set;
0212 writel(val, aemif->base + offset);
0213
0214 return 0;
0215 }
0216
0217 static inline int aemif_cycles_to_nsec(int val, unsigned long clk_rate)
0218 {
0219 return ((val + 1) * NSEC_PER_MSEC) / clk_rate;
0220 }
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231 static void aemif_get_hw_params(struct platform_device *pdev, int csnum)
0232 {
0233 struct aemif_device *aemif = platform_get_drvdata(pdev);
0234 struct aemif_cs_data *data = &aemif->cs_data[csnum];
0235 unsigned long clk_rate = aemif->clk_rate;
0236 u32 val, offset;
0237
0238 offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4;
0239 val = readl(aemif->base + offset);
0240
0241 data->ta = aemif_cycles_to_nsec(TA_VAL(val), clk_rate);
0242 data->rhold = aemif_cycles_to_nsec(RHOLD_VAL(val), clk_rate);
0243 data->rstrobe = aemif_cycles_to_nsec(RSTROBE_VAL(val), clk_rate);
0244 data->rsetup = aemif_cycles_to_nsec(RSETUP_VAL(val), clk_rate);
0245 data->whold = aemif_cycles_to_nsec(WHOLD_VAL(val), clk_rate);
0246 data->wstrobe = aemif_cycles_to_nsec(WSTROBE_VAL(val), clk_rate);
0247 data->wsetup = aemif_cycles_to_nsec(WSETUP_VAL(val), clk_rate);
0248 data->enable_ew = EW_VAL(val);
0249 data->enable_ss = SSTROBE_VAL(val);
0250 data->asize = val & ASIZE_MAX;
0251 }
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261 static int of_aemif_parse_abus_config(struct platform_device *pdev,
0262 struct device_node *np)
0263 {
0264 struct aemif_device *aemif = platform_get_drvdata(pdev);
0265 struct aemif_cs_data *data;
0266 u32 cs;
0267 u32 val;
0268
0269 if (of_property_read_u32(np, "ti,cs-chipselect", &cs)) {
0270 dev_dbg(&pdev->dev, "cs property is required");
0271 return -EINVAL;
0272 }
0273
0274 if (cs - aemif->cs_offset >= NUM_CS || cs < aemif->cs_offset) {
0275 dev_dbg(&pdev->dev, "cs number is incorrect %d", cs);
0276 return -EINVAL;
0277 }
0278
0279 if (aemif->num_cs >= NUM_CS) {
0280 dev_dbg(&pdev->dev, "cs count is more than %d", NUM_CS);
0281 return -EINVAL;
0282 }
0283
0284 data = &aemif->cs_data[aemif->num_cs];
0285 data->cs = cs;
0286
0287
0288 aemif_get_hw_params(pdev, aemif->num_cs++);
0289
0290
0291 if (!of_property_read_u32(np, "ti,cs-min-turnaround-ns", &val))
0292 data->ta = val;
0293
0294 if (!of_property_read_u32(np, "ti,cs-read-hold-ns", &val))
0295 data->rhold = val;
0296
0297 if (!of_property_read_u32(np, "ti,cs-read-strobe-ns", &val))
0298 data->rstrobe = val;
0299
0300 if (!of_property_read_u32(np, "ti,cs-read-setup-ns", &val))
0301 data->rsetup = val;
0302
0303 if (!of_property_read_u32(np, "ti,cs-write-hold-ns", &val))
0304 data->whold = val;
0305
0306 if (!of_property_read_u32(np, "ti,cs-write-strobe-ns", &val))
0307 data->wstrobe = val;
0308
0309 if (!of_property_read_u32(np, "ti,cs-write-setup-ns", &val))
0310 data->wsetup = val;
0311
0312 if (!of_property_read_u32(np, "ti,cs-bus-width", &val))
0313 if (val == 16)
0314 data->asize = 1;
0315 data->enable_ew = of_property_read_bool(np, "ti,cs-extended-wait-mode");
0316 data->enable_ss = of_property_read_bool(np, "ti,cs-select-strobe-mode");
0317 return 0;
0318 }
0319
0320 static const struct of_device_id aemif_of_match[] = {
0321 { .compatible = "ti,davinci-aemif", },
0322 { .compatible = "ti,da850-aemif", },
0323 {},
0324 };
0325 MODULE_DEVICE_TABLE(of, aemif_of_match);
0326
0327 static int aemif_probe(struct platform_device *pdev)
0328 {
0329 int i;
0330 int ret = -ENODEV;
0331 struct device *dev = &pdev->dev;
0332 struct device_node *np = dev->of_node;
0333 struct device_node *child_np;
0334 struct aemif_device *aemif;
0335 struct aemif_platform_data *pdata;
0336 struct of_dev_auxdata *dev_lookup;
0337
0338 aemif = devm_kzalloc(dev, sizeof(*aemif), GFP_KERNEL);
0339 if (!aemif)
0340 return -ENOMEM;
0341
0342 pdata = dev_get_platdata(&pdev->dev);
0343 dev_lookup = pdata ? pdata->dev_lookup : NULL;
0344
0345 platform_set_drvdata(pdev, aemif);
0346
0347 aemif->clk = devm_clk_get(dev, NULL);
0348 if (IS_ERR(aemif->clk)) {
0349 dev_err(dev, "cannot get clock 'aemif'\n");
0350 return PTR_ERR(aemif->clk);
0351 }
0352
0353 ret = clk_prepare_enable(aemif->clk);
0354 if (ret)
0355 return ret;
0356
0357 aemif->clk_rate = clk_get_rate(aemif->clk) / MSEC_PER_SEC;
0358
0359 if (np && of_device_is_compatible(np, "ti,da850-aemif"))
0360 aemif->cs_offset = 2;
0361 else if (pdata)
0362 aemif->cs_offset = pdata->cs_offset;
0363
0364 aemif->base = devm_platform_ioremap_resource(pdev, 0);
0365 if (IS_ERR(aemif->base)) {
0366 ret = PTR_ERR(aemif->base);
0367 goto error;
0368 }
0369
0370 if (np) {
0371
0372
0373
0374
0375
0376
0377 for_each_available_child_of_node(np, child_np) {
0378 ret = of_aemif_parse_abus_config(pdev, child_np);
0379 if (ret < 0) {
0380 of_node_put(child_np);
0381 goto error;
0382 }
0383 }
0384 } else if (pdata && pdata->num_abus_data > 0) {
0385 for (i = 0; i < pdata->num_abus_data; i++, aemif->num_cs++) {
0386 aemif->cs_data[i].cs = pdata->abus_data[i].cs;
0387 aemif_get_hw_params(pdev, i);
0388 }
0389 }
0390
0391 for (i = 0; i < aemif->num_cs; i++) {
0392 ret = aemif_config_abus(pdev, i);
0393 if (ret < 0) {
0394 dev_err(dev, "Error configuring chip select %d\n",
0395 aemif->cs_data[i].cs);
0396 goto error;
0397 }
0398 }
0399
0400
0401
0402
0403
0404 if (np) {
0405 for_each_available_child_of_node(np, child_np) {
0406 ret = of_platform_populate(child_np, NULL,
0407 dev_lookup, dev);
0408 if (ret < 0) {
0409 of_node_put(child_np);
0410 goto error;
0411 }
0412 }
0413 } else if (pdata) {
0414 for (i = 0; i < pdata->num_sub_devices; i++) {
0415 pdata->sub_devices[i].dev.parent = dev;
0416 ret = platform_device_register(&pdata->sub_devices[i]);
0417 if (ret) {
0418 dev_warn(dev, "Error register sub device %s\n",
0419 pdata->sub_devices[i].name);
0420 }
0421 }
0422 }
0423
0424 return 0;
0425 error:
0426 clk_disable_unprepare(aemif->clk);
0427 return ret;
0428 }
0429
0430 static int aemif_remove(struct platform_device *pdev)
0431 {
0432 struct aemif_device *aemif = platform_get_drvdata(pdev);
0433
0434 clk_disable_unprepare(aemif->clk);
0435 return 0;
0436 }
0437
0438 static struct platform_driver aemif_driver = {
0439 .probe = aemif_probe,
0440 .remove = aemif_remove,
0441 .driver = {
0442 .name = "ti-aemif",
0443 .of_match_table = of_match_ptr(aemif_of_match),
0444 },
0445 };
0446
0447 module_platform_driver(aemif_driver);
0448
0449 MODULE_AUTHOR("Murali Karicheri <m-karicheri2@ti.com>");
0450 MODULE_AUTHOR("Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>");
0451 MODULE_DESCRIPTION("Texas Instruments AEMIF driver");
0452 MODULE_LICENSE("GPL v2");
0453 MODULE_ALIAS("platform:" KBUILD_MODNAME);