Lines Matching +full:cs +full:- +full:x
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2010 - 2013 Texas Instruments Incorporated. http://www.ti.com/
8 * Murali Karicheri <m-[email protected]>
16 #include <linux/memory/ti-aemif.h>
33 #define TA(x) ((x) << TA_SHIFT) argument
34 #define RHOLD(x) ((x) << RHOLD_SHIFT) argument
35 #define RSTROBE(x) ((x) << RSTROBE_SHIFT) argument
36 #define RSETUP(x) ((x) << RSETUP_SHIFT) argument
37 #define WHOLD(x) ((x) << WHOLD_SHIFT) argument
38 #define WSTROBE(x) ((x) << WSTROBE_SHIFT) argument
39 #define WSETUP(x) ((x) << WSETUP_SHIFT) argument
40 #define EW(x) ((x) << EW_SHIFT) argument
41 #define SSTROBE(x) ((x) << SSTROBE_SHIFT) argument
55 #define TA_VAL(x) (((x) & TA(TA_MAX)) >> TA_SHIFT) argument
56 #define RHOLD_VAL(x) (((x) & RHOLD(RHOLD_MAX)) >> RHOLD_SHIFT) argument
57 #define RSTROBE_VAL(x) (((x) & RSTROBE(RSTROBE_MAX)) >> RSTROBE_SHIFT) argument
58 #define RSETUP_VAL(x) (((x) & RSETUP(RSETUP_MAX)) >> RSETUP_SHIFT) argument
59 #define WHOLD_VAL(x) (((x) & WHOLD(WHOLD_MAX)) >> WHOLD_SHIFT) argument
60 #define WSTROBE_VAL(x) (((x) & WSTROBE(WSTROBE_MAX)) >> WSTROBE_SHIFT) argument
61 #define WSETUP_VAL(x) (((x) & WSETUP(WSETUP_MAX)) >> WSETUP_SHIFT) argument
62 #define EW_VAL(x) (((x) & EW(EW_MAX)) >> EW_SHIFT) argument
63 #define SSTROBE_VAL(x) (((x) & SSTROBE(SSTROBE_MAX)) >> SSTROBE_SHIFT) argument
85 * struct aemif_cs_data: structure to hold CS parameters
87 * @cs: chip-select number
94 u8 cs; member
105 * @num_cs: number of assigned chip-selects
106 * @cs_offset: start number of cs nodes
107 * @cs_data: array of chip-select settings
108 * @config_cs_lock: lock used to access CS configuration
121 * aemif_check_cs_timings() - Check the validity of a CS timing configuration.
128 if (timings->ta > TA_MAX) in aemif_check_cs_timings()
129 return -EINVAL; in aemif_check_cs_timings()
131 if (timings->rhold > RHOLD_MAX) in aemif_check_cs_timings()
132 return -EINVAL; in aemif_check_cs_timings()
134 if (timings->rstrobe > RSTROBE_MAX) in aemif_check_cs_timings()
135 return -EINVAL; in aemif_check_cs_timings()
137 if (timings->rsetup > RSETUP_MAX) in aemif_check_cs_timings()
138 return -EINVAL; in aemif_check_cs_timings()
140 if (timings->whold > WHOLD_MAX) in aemif_check_cs_timings()
141 return -EINVAL; in aemif_check_cs_timings()
143 if (timings->wstrobe > WSTROBE_MAX) in aemif_check_cs_timings()
144 return -EINVAL; in aemif_check_cs_timings()
146 if (timings->wsetup > WSETUP_MAX) in aemif_check_cs_timings()
147 return -EINVAL; in aemif_check_cs_timings()
154 * aemif_set_cs_timings() - Set the timing configuration of a given chip select.
156 * @cs: index of the chip select to configure
161 int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, in aemif_set_cs_timings() argument
169 return -EINVAL; in aemif_set_cs_timings()
171 if (cs > aemif->num_cs) in aemif_set_cs_timings()
172 return -EINVAL; in aemif_set_cs_timings()
178 set = TA(timings->ta) | RHOLD(timings->rhold) | RSTROBE(timings->rstrobe) | in aemif_set_cs_timings()
179 RSETUP(timings->rsetup) | WHOLD(timings->whold) | in aemif_set_cs_timings()
180 WSTROBE(timings->wstrobe) | WSETUP(timings->wsetup); in aemif_set_cs_timings()
182 offset = A1CR_OFFSET + cs * 4; in aemif_set_cs_timings()
184 mutex_lock(&aemif->config_cs_lock); in aemif_set_cs_timings()
185 val = readl(aemif->base + offset); in aemif_set_cs_timings()
188 writel(val, aemif->base + offset); in aemif_set_cs_timings()
189 mutex_unlock(&aemif->config_cs_lock); in aemif_set_cs_timings()
196 * aemif_calc_rate - calculate timing data.
208 result = DIV_ROUND_UP((wanted * clk), NSEC_PER_MSEC) - 1; in aemif_calc_rate()
210 dev_dbg(&pdev->dev, "%s: result %d from %ld, %d\n", __func__, result, in aemif_calc_rate()
221 * aemif_config_abus - configure async bus parameters
230 * chip-select.
237 struct aemif_cs_data *data = &aemif->cs_data[csnum]; in aemif_config_abus()
241 offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; in aemif_config_abus()
243 set = (data->asize & ACR_ASIZE_MASK); in aemif_config_abus()
244 if (data->enable_ew) in aemif_config_abus()
246 if (data->enable_ss) in aemif_config_abus()
249 mutex_lock(&aemif->config_cs_lock); in aemif_config_abus()
250 val = readl(aemif->base + offset); in aemif_config_abus()
253 writel(val, aemif->base + offset); in aemif_config_abus()
254 mutex_unlock(&aemif->config_cs_lock); in aemif_config_abus()
256 return aemif_set_cs_timings(aemif, data->cs - aemif->cs_offset, &data->timings); in aemif_config_abus()
260 * aemif_get_hw_params - function to read hw register values
271 struct aemif_cs_data *data = &aemif->cs_data[csnum]; in aemif_get_hw_params()
274 offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; in aemif_get_hw_params()
275 val = readl(aemif->base + offset); in aemif_get_hw_params()
277 data->timings.ta = TA_VAL(val); in aemif_get_hw_params()
278 data->timings.rhold = RHOLD_VAL(val); in aemif_get_hw_params()
279 data->timings.rstrobe = RSTROBE_VAL(val); in aemif_get_hw_params()
280 data->timings.rsetup = RSETUP_VAL(val); in aemif_get_hw_params()
281 data->timings.whold = WHOLD_VAL(val); in aemif_get_hw_params()
282 data->timings.wstrobe = WSTROBE_VAL(val); in aemif_get_hw_params()
283 data->timings.wsetup = WSETUP_VAL(val); in aemif_get_hw_params()
284 data->enable_ew = EW_VAL(val); in aemif_get_hw_params()
285 data->enable_ss = SSTROBE_VAL(val); in aemif_get_hw_params()
286 data->asize = val & ASIZE_MAX; in aemif_get_hw_params()
290 * of_aemif_parse_abus_config - parse CS configuration from DT
295 * configured in a cs device binding node.
301 unsigned long clk_rate = aemif->clk_rate; in of_aemif_parse_abus_config()
303 u32 cs; in of_aemif_parse_abus_config() local
306 if (of_property_read_u32(np, "ti,cs-chipselect", &cs)) { in of_aemif_parse_abus_config()
307 dev_dbg(&pdev->dev, "cs property is required"); in of_aemif_parse_abus_config()
308 return -EINVAL; in of_aemif_parse_abus_config()
311 if (cs - aemif->cs_offset >= NUM_CS || cs < aemif->cs_offset) { in of_aemif_parse_abus_config()
312 dev_dbg(&pdev->dev, "cs number is incorrect %d", cs); in of_aemif_parse_abus_config()
313 return -EINVAL; in of_aemif_parse_abus_config()
316 if (aemif->num_cs >= NUM_CS) { in of_aemif_parse_abus_config()
317 dev_dbg(&pdev->dev, "cs count is more than %d", NUM_CS); in of_aemif_parse_abus_config()
318 return -EINVAL; in of_aemif_parse_abus_config()
321 data = &aemif->cs_data[aemif->num_cs]; in of_aemif_parse_abus_config()
322 data->cs = cs; in of_aemif_parse_abus_config()
325 aemif_get_hw_params(pdev, aemif->num_cs++); in of_aemif_parse_abus_config()
328 if (!of_property_read_u32(np, "ti,cs-min-turnaround-ns", &val)) in of_aemif_parse_abus_config()
329 data->timings.ta = aemif_calc_rate(pdev, val, clk_rate); in of_aemif_parse_abus_config()
331 if (!of_property_read_u32(np, "ti,cs-read-hold-ns", &val)) in of_aemif_parse_abus_config()
332 data->timings.rhold = aemif_calc_rate(pdev, val, clk_rate); in of_aemif_parse_abus_config()
334 if (!of_property_read_u32(np, "ti,cs-read-strobe-ns", &val)) in of_aemif_parse_abus_config()
335 data->timings.rstrobe = aemif_calc_rate(pdev, val, clk_rate); in of_aemif_parse_abus_config()
337 if (!of_property_read_u32(np, "ti,cs-read-setup-ns", &val)) in of_aemif_parse_abus_config()
338 data->timings.rsetup = aemif_calc_rate(pdev, val, clk_rate); in of_aemif_parse_abus_config()
340 if (!of_property_read_u32(np, "ti,cs-write-hold-ns", &val)) in of_aemif_parse_abus_config()
341 data->timings.whold = aemif_calc_rate(pdev, val, clk_rate); in of_aemif_parse_abus_config()
343 if (!of_property_read_u32(np, "ti,cs-write-strobe-ns", &val)) in of_aemif_parse_abus_config()
344 data->timings.wstrobe = aemif_calc_rate(pdev, val, clk_rate); in of_aemif_parse_abus_config()
346 if (!of_property_read_u32(np, "ti,cs-write-setup-ns", &val)) in of_aemif_parse_abus_config()
347 data->timings.wsetup = aemif_calc_rate(pdev, val, clk_rate); in of_aemif_parse_abus_config()
349 if (!of_property_read_u32(np, "ti,cs-bus-width", &val)) in of_aemif_parse_abus_config()
351 data->asize = 1; in of_aemif_parse_abus_config()
352 data->enable_ew = of_property_read_bool(np, "ti,cs-extended-wait-mode"); in of_aemif_parse_abus_config()
353 data->enable_ss = of_property_read_bool(np, "ti,cs-select-strobe-mode"); in of_aemif_parse_abus_config()
355 return aemif_check_cs_timings(&data->timings); in of_aemif_parse_abus_config()
359 { .compatible = "ti,davinci-aemif", },
360 { .compatible = "ti,da850-aemif", },
368 int ret = -ENODEV; in aemif_probe()
369 struct device *dev = &pdev->dev; in aemif_probe()
370 struct device_node *np = dev->of_node; in aemif_probe()
375 return -ENOMEM; in aemif_probe()
379 aemif->clk = devm_clk_get_enabled(dev, NULL); in aemif_probe()
380 if (IS_ERR(aemif->clk)) in aemif_probe()
381 return dev_err_probe(dev, PTR_ERR(aemif->clk), in aemif_probe()
384 aemif->clk_rate = clk_get_rate(aemif->clk) / MSEC_PER_SEC; in aemif_probe()
386 if (np && of_device_is_compatible(np, "ti,da850-aemif")) in aemif_probe()
387 aemif->cs_offset = 2; in aemif_probe()
389 aemif->base = devm_platform_ioremap_resource(pdev, 0); in aemif_probe()
390 if (IS_ERR(aemif->base)) in aemif_probe()
391 return PTR_ERR(aemif->base); in aemif_probe()
393 mutex_init(&aemif->config_cs_lock); in aemif_probe()
396 * For every controller device node, there is a cs device node in aemif_probe()
398 * functions iterate over these nodes and update the cs data in aemif_probe()
408 for (i = 0; i < aemif->num_cs; i++) { in aemif_probe()
412 aemif->cs_data[i].cs); in aemif_probe()
435 .name = "ti-aemif",
442 MODULE_AUTHOR("Murali Karicheri <m-[email protected]>");